SQL Server悲觀鎖和樂觀鎖

1、什麼悲觀鎖是?

在同一時間內只允許一個線程更新數據 ,在查詢的時候鎖住查詢出來的結果集,如果沒有加聚集索引那麼會鎖定整張表,鎖定期間可以新增和查詢數據。

go
CREATE TABLE T
(
    t_id int,
    t_name nvarchar(1024),
    t_count int,
    t_version int
)
go
insert into t(t_id,t_name,t_count,t_version ) values(1,'a',10000,0)
insert into t(t_id,t_name,t_count,t_version ) values(2,'b',10000,0)
declare @count as int = 0
begin tran
    select @count=t_count  from t WITH(UPDLOCK) where t_id = 1 
    WAITFOR DELAY '0:0:05' --延遲5秒
    update t set t_count=@count-1 where t_id = 1
commit TRAN

2、什麼是樂觀鎖?

樂觀鎖和悲觀鎖的概念相反。通常是用version字段來實現。

declare @count as int = 0
declare @v int = 0
begin tran
    select @count=t_count,@v=t_version  from t where t_id = 1 
    WAITFOR DELAY '0:0:05' --延遲5秒
    update t set t_count=@count-1,t_version = t_version + 1 where t_id = 1 and t_version = @v
commit TRAN

3、什麼時候用悲觀鎖?什麼時候用樂觀鎖?

選擇使用那一種鎖取決於訪問頻率和一旦產生衝突的嚴重性。如果系統被併發訪問的概率很低,或者衝突發生後的後果不太嚴重(所謂後果指被檢測到衝突的提交會失敗,必須重來一次),可以使用樂觀鎖,否則使用悲觀鎖。

例如有個修改用戶姓名的場景,有線程A、B。

樂觀鎖:如果在A線程事務提交之前B線程修改了用戶姓名,那麼A線程會修改失敗。修改失敗後可能會給用戶 “xxx 失敗”的提示,然後刷新當前數據,數據展示爲B線程修改後的數據,那麼此時用戶可能就會有疑問明明修改失敗了,怎麼還是修改了?剛剛還叫張三的呢,現在怎麼變成李四了?如果可以接受這種情況,那麼就可以使用樂觀鎖反之使用悲觀鎖。

悲觀鎖:A線程先將要修改的數據加鎖,在A線程事務還沒提交之前,B線程是不能修改的。

悲觀鎖類似避免衝突,樂觀鎖類似解決衝突。

4、其他擴展

鎖有兩種分類方法。
(1) 從數據庫系統的角度來看鎖分爲以下三種類型:

  • 獨佔鎖(Exclusive Lock)
    獨佔鎖鎖定的資源只允許進行鎖定操作的程序使用,其它任何對它的操作均不會被接受。執行數據更新命令,即INSERT、 UPDATE 或DELETE 命令時,SQL Server 會自動使用獨佔鎖。但當對象上有其它鎖存在時,無法對其加獨佔鎖。獨佔鎖一直到事務結束才能被釋放。
  • 共享鎖(Shared Lock)
    共享鎖鎖定的資源可以被其它用戶讀取,但其它用戶不能修改它。在SELECT 命令執行時,SQL Server 通常會對對象進行共享鎖鎖定。通常加共享鎖的數據頁被讀取完畢後,共享鎖就會立即被釋放。
  • 更新鎖(Update Lock)
    更新鎖是爲了防止死鎖而設立的。當SQL Server 準備更新數據時,它首先對數據對象作更新鎖鎖定,這樣數據將不能被修改,但可以讀取。等到SQL Server 確定要進行更新數據操作時,它會自動將更新鎖換爲獨佔鎖。但當對象上有其它鎖存在時,無法對其作更新鎖鎖定。

(2)從程序員的角度看
鎖分爲以下兩種類型:

  • 樂觀鎖(Optimistic Lock)
  • 悲觀鎖(Pessimistic Lock)

參考文章

https://www.cnblogs.com/knowledgesea/p/3714417.html

https://blog.csdn.net/sd4015700/article/details/50162965?locationNum=9

https://www.cnblogs.com/sunshch/archive/2013/04/02/2994781.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章