關於資料庫中的樂觀鎖與悲觀鎖

2021-10-05 08:26:04 字數 1419 閱讀 2228

概念:樂觀鎖假定資料一般情況下不會發生併發衝突,是相對於悲觀鎖而言的。所以在資料進行提交更新時,才會正式對資料的衝突與否進行檢測,如果發現衝突了,則讓使用者返回錯誤資訊,並讓使用者決定如何去做。

實現:在對資料庫進行處理時,樂觀鎖並不會使用資料庫提供的鎖機制,而是基於資料版本(version)記錄機制來實現樂觀鎖。例:update table set columna = 1,version=version+1 where id=# and version = #。在讀取資料時將版本標識一起讀出,資料每發生一次更新,版本值加1,。在提交更新時,比較讀到的資料與提交時的資料是否一致,如果一致則予以更新,提交後修改版本標識,不一致時可以採取丟棄和再次嘗試的策略。

優點:程式實現,樂觀鎖並未真正加鎖,所以不會產生任何鎖和死鎖。更新資料的速度提高了。

缺點:當應用併發量高的時候,version值在頻繁變化,則會導致大量請求失敗,影響系統的可用性。

適用場景:樂觀鎖比較適合併發量不高,並且寫操作不頻繁的場景

概念:悲觀鎖,就是對資料的衝突採取一種悲觀的態度。悲觀鎖就是在讀取資料的時候,為了不讓別人修改自己讀取的資料,就會先對自己讀取的資料加鎖,只有自己把資料讀完了,才允許別人修改那部分資料,或者反過來說,就是自己修改某條資料的時候,不允許別人讀取該資料,只有等自己的整個事務提交了,才釋放自己加上的鎖,才允許其他使用者訪問那部分資料。

實現:悲觀鎖的實現,往往依靠資料庫提供的鎖機制,即對查詢語句新增for update關鍵字。例:select * from table where id = 1 for update。在對記錄進行修改前,先嘗試為該記錄加上排他鎖(exclusive locking)。如果加鎖失敗,說明該記錄正在被修改,那麼當前查詢可能要等待或者丟擲異常。如果成功加鎖,那麼就可以對記錄做修改,事務完成後就會解鎖了。其間如果有其他事務對該記錄做加鎖的操作,都要等待當前事務解鎖或直接丟擲異常。

注意:要使用悲觀鎖,我們必須關閉mysql資料庫中自動提交的屬性,因為mysql預設使用autocommit模式,當你執行乙個更新操作後,mysql會立刻將結果進行提交。命令set autocommit=0;關閉了mysql的autocommit,因此需要手動控制事務的提交。

優點:悲觀鎖可以嚴格保證資料訪問的安全,更新失敗的概率比較低。

缺點:悲觀鎖依賴資料庫鎖,效率低。每次請求都會額外產生加鎖的開銷且未獲取到鎖的請求將會阻塞等待鎖的獲取,在高併發環境下,容易造成大量請求阻塞,影響系統可用性。另外,悲觀鎖使用不當還可能產生死鎖的情況。

適用場景:悲觀鎖比較適合併發量較小又需要獨佔讀取結果並依賴讀取的結果進行判斷的業務場景

資料庫樂觀鎖與悲觀鎖

每次拿資料的時候都會擔心會被別人修改 疑心重很悲觀 所以每次在拿資料的時候都會上鎖。確保自己使用的過程中不會被別人訪問,自己使用完後再解鎖。期間需要訪問該資料的都會等待。每次拿資料的時候都完全不擔心會被別人修改 心態好很樂觀 所以每次在拿資料的時候都不會上鎖。但是在更新資料的時候去判斷該期間是否被別...

資料庫樂觀鎖與悲觀鎖

演示案例 為何需要樂觀鎖,與悲觀鎖這樣的鎖?idname money 1god 1000 假設god同志的賬上有1000元,現在有兩個執行緒同時往他的賬戶上轉錢。1.a執行緒準備向god賬戶上轉200,讀取到賬戶上有1000元,事務還未提交 2.b執行緒準備向god賬戶上轉100,讀取到賬戶上有10...

資料庫 樂觀鎖與悲觀鎖

總是認為不會產生併發問題,每次去取資料的時候總認為不會有其他執行緒對資料進行修改,因此不會上鎖,但是在更新時會判斷其他執行緒在這之前有沒有對資料進行修改,一般會使用版本號機制或cas操作實現。update table set x x 1,version version 1 where id and ...