樂觀鎖與悲觀鎖
阿新 • • 發佈:2019-12-31
排他鎖
- 排它鎖,加鎖後別的使用者可以讀取資料,但是不能更改資料
- mysql中, for update 是一種使用排它鎖的方式
- 通過主鍵選中的。那麼這個時候是行級鎖
- 選中的條件不明確包含主鍵。這個時候會鎖表
悲觀鎖
悲觀鎖的簡介
- 悲觀鎖:當我們要對一個資料庫中的一條資料進行修改的時候,為了避免同時被其他人修改,最好的辦法就是直接對該資料進行加鎖以防止併發。
- 悲觀併發控制實際上是“先取鎖再訪問”的保守策略,為資料處理的安全提供了保證。
- 但是在效率方面,處理加鎖的機制會讓資料庫產生額外的開銷,還有增加產生死鎖的機會,同時也會降低併發效能
悲觀鎖的實現
-
注意: 要使用悲觀鎖,我們必須關閉mysql資料庫的自動提交屬性。MySQL預設使用autocommit模式,也就是說,當你執行一個更新操作後,MySQL會立刻將結果進行提交。我們可以使用命令設定MySQL為非autocommit模式:set autocommit=0;
-
舉一個栗子
//開始事務 begin; //查詢出商品庫存資訊,使用 for update 加上排它鎖 select quantity from items where id=1 for update; //修改商品庫存 update items set quantity=100 where id = 1; //提交事務 commit; 複製程式碼
樂觀鎖
樂觀鎖的簡介
- 樂觀鎖在資料進行提交更新的時候,才會正式對資料的衝突與否進行檢測
- 相對於悲觀鎖,在對資料庫進行處理的時候,樂觀鎖並不會使用資料庫提供的鎖機制。一般的實現樂觀鎖的方式就是記錄資料版本。
- 樂觀鎖不會產生任何鎖和死鎖,擁有更好的效能。
樂觀鎖的實現
-
通過一個單獨的可以順序遞增的version欄位,可以避免ABA問題:
//查詢出商品資訊,version = 1 select version from items where id=1 //修改商品庫存為2 update items set quantity=2,version = 3 where id=1 and version = 2; 複製程式碼
除了version以外,還可以使用時間戳,因為時間戳天然具有順序遞增性。
-
減小樂觀鎖力度,可以最大程度的提升吞吐率,提高併發能力:
//修改商品庫存 update item set quantity=quantity - 1 where id = 1 and quantity - 1 > 0 複製程式碼
悲觀鎖和樂觀鎖,該選擇哪個?
- 樂觀鎖並未真正加鎖,效率高。然而,如果鎖的粒度掌握不好,更新失敗的概率就會比較高,容易發生業務失敗。
- 悲觀鎖依賴資料庫鎖,效率低。更新失敗的概率比較低。
- 在高併發的業務場景下,悲觀鎖越來越少被使用了。