2016-08-03 42 views
3

我試圖在SQL Server Management Studio中執行以下兩個查詢(在單獨的查詢窗口中)。我按照我在這裏輸入的順序運行它們。閱讀提交與可重複閱讀示例

當隔離級別設置爲READ COMMITTED時,它們執行正常,但當它設置爲REPEATABLE READS時,事務處於未鎖定狀態。

你能幫我理解這裏死鎖嗎?

第一:

begin tran 
declare @a int, @b int 
set @a = (select col1 from Test where id = 1) 
set @b = (select col1 from Test where id = 2) 
waitfor delay '00:00:10' 
update Test set col1 = @a + @b where id = 1 
update Test set col1 = @a - @b where id = 2 
commit 

二:

begin tran 
update Test set col1 = -1 where id = 1 
commit 

UPD答案是laready給出,但如下因素的建議,我將僵局圖

enter image description here

+0

你有沒有嘗試在探查器中創建死鎖圖? – SQLChao

回答

1

在這兩種情況下,選擇使用共享鎖並更新獨佔鎖。

在READ COMMITTED模式下,共享鎖在選擇完成後立即釋放。

在REPEATABLE READS模式中,選擇的共享鎖持有直到事務結束,以確保沒有其他會話可以更改讀取的數據。在同一個交易中新的讀取被允許產生相同的結果,除非數據在當前會話/交易中被改變

本來我認爲,你在兩次會話中都執行了「第一次」。然後,解釋將變得微不足道:兩個會話都會獲取並獲取共享鎖,然後會阻止更新所需的排它鎖。

第二個會話只進行更新的情況稍微複雜一點。更新程序會首先獲取更新鎖(UPDLOCK),用於選擇必須更新的行,這可能類似於共享鎖,但至少不會被共享鎖阻止。接下來,當數據實際更新時,它會嘗試將更新鎖轉換爲排它鎖,因爲第一個會話仍然保持共享鎖,所以失敗。現在兩個會話互相阻塞。