微軟SQL Server事務隔離級別簡介

微軟SQL Server事務隔離級別簡介

數據庫的事務隔離級別(TRANSACTION ISOLATION LEVEL)是一個數據庫上很基本的一個概念。爲什麼會有事務隔離級別,SQL Server上實現了哪些事務隔離級別?事務隔離級別的前提是一個多用戶、多進程、多線程的併發系統,在這個系統中爲了保證數據的一致性和完整性,我們引入了事務隔離級別這個概念,對一個單用戶、單線程的應用來說則不存在這個問題。

首先,我們來看一下高併發的系統中會存在哪些問題,爲了便於理解我們以張三在招商銀行的賬號和存款爲例。

一、準備工作:

1. 創建一個銀行賬號Table(只是爲了說明問題,不考慮表的設計範式)
CREATE TABLE dbo.BankAccount
(
   BankAccountId CHAR(16)       NOTNULL, -- 銀行賬號
   UserName      NVARCHAR(32)  NOT NULL, -- 用戶
   Balance       DECIMAL(19, 2) NOTNULL, -- 餘額
   LastUpdate    SMALLDATETIME  NOT NULL
)
GO

2. 準備數據
INSERT INTO dbo.BankAccount
     VALUES ('9555500100071120', N'張三', 10000.00, GETDATE()) -- 北京分行賬號
INSERT INTO dbo.BankAccount
     VALUES ('9555507551227787', N'張三', 20000.00, GETDATE()) -- 深圳分行賬號
GO

3. 查看數據
SELECT * FROM dbo.BankAccount

二、應用場景

假設張三在招商銀行開設了兩個賬號,一個是招商銀行北京分行,一個是招商銀行深圳分行,兩個賬號的餘額分別是10,000和20,000。

1.       張三在網上做了一筆交易,交易額100,買方小王通過銀行匯款100到張三的北京分行的賬號(見下面左圖),櫃檯操作人員向張三賬號存入100(事務一),然後系統些操作日誌(假設需要10秒,WAITFOR DELAY '00:00:10')正在此時張三在ATM查了一下賬號上餘額(事務二),發現已經是10100,於是回去準備發貨,但是事務一在寫操作日誌時超時,這是事務回滾,存款交易被取消,錢退給了小王,這樣張三查到的賬號餘額事實上是事務一還沒有提交的數據,導致張三錯誤的認爲已經收到交易款項。
 

2.      

3.      
一個事務讀到另外一個事務還沒有提交的數據,我們稱之爲髒讀。
解決方法:把事務隔離級別調整到READ COMMITTED,即把右上圖中的SET TRAN ISOLATION LEVEL READ UNCOMMITTED更改成下圖中的SET TRAN ISOLATION LEVEL READ COMMITTED。這時我們重複上面的動作會發現事務二會一直等到事務一執行完畢再返回結果,因爲此時事務以已經把自己的更改ROLLBACK了,所以事務二可以返回正確的結果。

2. 張三先後兩次查詢某一賬號的餘額,在兩次查詢期間,小王完成了銀行轉賬,導致兩次的查詢結果不同。

 
一個事務先後讀取同一條記錄,但兩次讀取的數據不同,我們稱之爲不可重複讀。
解決方法:把事務隔離級別調整到REPEATABLE READ。在下圖中使用SET TRAN ISOLATION LEVEL REPEATABLE READ。這時我們重複上面的動作會發現事務二會一直等到事務一執行完畢再返回結果。

3. 張三妻子先後兩次查詢張三招商銀行所有賬號的總餘額,而在此期間張三在廣州招商銀行分行成功開設了一個賬號,並存入5000,導致張三妻子兩次查詢的總餘額不同,在此期間張三原有兩個賬號的餘額均未發生改變。
 
一個事務先後讀取一個範圍的記錄,但兩次讀取的紀錄數不同,我們稱之爲幻象讀。
解決方法:把事務隔離級別調整到SERIALIZABLE。在下圖中使用SET TRANISOLATION LEVEL SERIALIZABLE。這時我們重複上面的動作會發現事務二會一直等到事務一執行完畢再返回結果。

 

三、總結

事務隔離級別是通過數據庫的鎖機制來控制的,在不同的應用場景需要應用不同的事務隔離級別,SQL Server默認的事務隔離級別是READCOMMITTED,默認的隔離級別,已經可以滿足我們大部分應用的需求。

 


發佈了45 篇原創文章 · 獲贊 2 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章