UPDLOCK.UPDLOCK 的優點是允許您讀取數據(不阻塞其它事務)並在以后更新數據,同時確保自從上次讀取數據后數據沒有被更改。當我們用UPDLOCK來讀取記錄時可以對取到的記錄加上更新鎖,從而加上鎖的記錄在其它的線程中是不能更改的只能等本線程的事務結束后才能更改.
測試:
在另一個查詢里:
BEGIN TRANSACTION
SELECT * FROM myTable WITH (UPDLOCK) WHERE Id in (1,2,3)
waitfor delay '00:00:10'
update myTable set [Name]='ZZ' where Id in (1,2,3)
commit TRANSACTION
在另一個查詢里:
SELECT * FROM myTable WHERE Id in (1,2,3)
可以馬上查詢到數據。
但如果要更新數據,必須等其他更新鎖釋放后才能執行。
update myTable set [Name]='ZZ' where Id in (1,2,3)
這就說明,有時候需要控制某條記錄在我讀取后就不許再進行更新,那么我就可以將所有要處理當前記錄的查詢都加上更新鎖,以防止查詢后被其它事務修改.將事務的影響降低到最小
如果不使用這個鎖的話,在項目中很有可能出現“事務(進程 ID )與另一個進程已被死鎖在 lock 資源上,且該事務已被選作死鎖犧牲品。請重新運行”錯誤。
例如:
表現二:
用戶A讀一條紀錄,然后修改該條紀錄
這是用戶B修改該條紀錄
這里用戶A的事務里鎖的性質由共享鎖企圖上升到獨占鎖(for update),而用戶B里的獨占鎖由於A有共享鎖存在所以必須等A釋放掉共享鎖,而A由於B的獨占鎖而無法上升的獨占鎖也就不可能釋放共享鎖,於是出現了死鎖。
這種死鎖比較隱蔽,但其實在稍大點的項目中經常發生。
解決方法:
讓用戶A的事務(即先讀后寫類型的操作),在select 時就是用Update lock
語法如下:
select * from table1 with(updlock) where ....