一直沒有認真了解
update
操作的鎖,最近在
msdn論壇
上看到乙個問題,詢問堆表更新的死鎖問題,問題很簡單,有類似這樣的表及資料:
create
table
dbo.tb(
c1int,c2
char
(10),
c3varchar
(10)
);go
declare
@idint
;set
@id= 0;
while
@id<5
begin
;set
@id=
@id+ 1;
insert
dbo.
tbvalues
(@id
,'b'
+right(10000 +
@id, 4),
'c'+
right(100000 +
@id, 4)
);end
;在查詢一中執行更新操作:
begin
tran
update
dbo.
tbsetc2=
'xx'
where
c1= 2;
waitfor
delay
'00:00:30'
;update
dbo.
tbsetc2=
'xx'
where
c1= 5;
rollback
;在查詢一執行開始後,馬上在查詢二中執行下面的操作
begin
tran
update
dbo.
tbsetc2=
'xx'
where
c1= 1;
rollback
;為什麼會出現死鎖,如果條件改為 c1 = 4 則不會死鎖。
開始的時候想得比較簡單,死鎖的表現是形成迴圈等待(對於兩個查詢而言,可以簡單地認為就是在相互等待對方鎖定資源的釋放)。
對於這個例子而言,第乙個查詢更新兩次,會先更新並鎖定一條記錄,然後等待第二個更新;但第二個查詢只會更新一條記錄,它要麼與第乙個查詢衝突,無法獲得鎖,需要等待查詢一完成,這個時候它並沒有鎖定什麼;要麼能夠獲得鎖,完成更新。似乎不應該會出現死鎖,死鎖會不會是其他原因導致。
在自己的電腦上簡單測試了一下,似乎也確實沒有死鎖。
但後面通過profile跟蹤更新操作的下鎖情況才發現,自己的分析大錯特錯了。主要原因在於沒有正確理解更新操作是如何用鎖的。
在聯機幫助上
「鎖模式
」中有關於更新的u(更新鎖)和x(排它鎖)的說明
不過說得確實挺模糊的,裡面還提到了s鎖,我一直以為是查詢資料過程中用的s鎖(也 select 一樣),找到滿足條件的記錄後用u鎖,再轉換為x鎖做更新。
profile
(事件探查器)跟蹤的結果讓我知道了這是乙個錯誤的理解,在profile中新建乙個跟蹤,選擇locks中的
lock:
acquired
(加鎖),
lock:
acquired
(釋放鎖)
解兩個事件,在篩選中設定只跟蹤測試用的查詢視窗對應的spid(可以執行
@@spid
獲得),然後執行乙個更新語句,比如
update
dbo.
tbsetc2=
'xx'
where
c1= 3
在profile中可以看到,對於每條記錄都有加 u 鎖的操作,對於不滿足條件的記錄,會馬上釋放u鎖;對於滿足條件的記錄,最終轉換為x鎖。如下圖所示。
注意一下,在這個跟蹤結果裡面,並沒有出現s鎖。
另外學做了一些測試:
通過加大記錄量做更新測試,會發現資料掃瞄涉及的記錄都有u鎖,並不限於更新記錄所在的頁。這從另乙個角度說明了大表中scan 可怕。
當使用索引scan的時候,也會通過跟蹤發現所scan的索引資源有u鎖,如果更新不涉及索引變化,那以只會對應的記錄有u轉x鎖,索引的u鎖會釋放;如果影響索引,那麼索引的u鎖會轉x鎖。
刪除操作與更新操作類似
使用 update
asetc2=
'xx'
from
dbo.
tbas
awith
(nolock
)where
c1= 3
的加鎖情況是一樣的, 並不會因為nolock的提示而不加u 或者x 鎖
最後回頭研究一下示例中的死鎖問題:
更新時,記錄讀取的順序,可以通過profile跟蹤的
lock:
acquired
(加鎖)
事件來看,涉及大量資料時,如果伺服器支援,還會有併發讀取。這也是分析死鎖時要考慮的因素
共享鎖 S鎖 和排它鎖 X鎖
共享鎖 讀取 操作建立的鎖。其他使用者可以併發讀取資料,但任何事物都不能獲取資料上的排它鎖,直到已釋放所有共享鎖。共享鎖 s鎖 又稱為讀鎖,若事務t對資料物件a加上s鎖,則事務t只能讀a 其他事務只能再對a加s鎖,而不能加x鎖,直到t釋放a上的s鎖。這就保證了其他事務可以讀a,但在t釋放a上的s鎖之...
共享鎖與排它鎖
根據自己理解,物件指行或者表 共享鎖 s鎖 又稱讀鎖,若事務t對資料物件a加上s鎖,則事務t可以讀a但不能修改a,其他事務只能再對a加s鎖,而不能加x鎖,直到t釋放a上的s鎖。這保證了其他事務可以讀a,但在t釋放a上的s鎖之前不能對a做任何修改。排他鎖 x鎖 又稱寫鎖。若事務t對資料物件a加上x鎖,...
共享鎖與排它鎖
共享鎖 s鎖 又稱讀鎖,若事務t對資料物件a加上s鎖,則事務t可以讀a但不能修改a,其他事務只能再對a加s鎖,而不能加x鎖,直到t釋放a上的s鎖。這保證了其他事務可以讀a,但在t釋放a上的s鎖之前不能對a做任何修改。排他鎖 x鎖 又稱寫鎖。若事務t對資料物件a加上x鎖,事務t可以讀a也可以修改a,其...