MySQL悲觀鎖和樂觀鎖

2022-10-09 12:57:11 字數 1703 閱讀 3963

引言:之所以叫做悲觀鎖,是因為這是一種對資料的修改抱有悲觀態度的併發控制方式。我們一般認為資料被併發修改的概率比較大,所以需要在修改之前先加鎖。

【例子】

//0.開始事務

begin;

//1.查詢出商品庫存資訊

select quantity from items where id=1 for update;

//2.修改商品庫存為2

update items set quantity=2 where id = 1;

//3.提交事務

commit;

以上,在對id = 1的記錄修改前,先通過for update的方式進行加鎖,然後再進行修改。這就是比較典型的悲觀鎖策略。

如果以上修改庫存的**發生併發,同一時間只有乙個執行緒可以開啟事務並獲得id=1的鎖,其它的事務必須等本次事務提交之後才能執行。這樣我們可以保證當前的資料不會被其它事務修改。

引言:相對於悲觀鎖,在對資料庫進行處理的時候,樂觀鎖並不會使用資料庫提供的鎖機制。一般的實現樂觀鎖的方式就是記錄資料版本。

【例子】

//查詢出商品庫存資訊,quantity = 3

select quantity from items where id=1

//修改商品庫存為2

update items set quantity=2 where id=1 and quantity = 3;

以上,我們在更新之前,先查詢一下庫存表中當前庫存數(quantity),然後在做update的時候,以庫存數作為乙個修改條件。當我們提交更新的時候,判斷資料庫表對應記錄的當前庫存數與第一次取出來的庫存數進行比對,如果資料庫表當前庫存數與第一次取出來的庫存數相等,則予以更新,否則認為是過期資料。

但是以上更新語句存在乙個比較重要的問題,即aba問題。

比如說乙個執行緒1從資料庫中取出庫存數3,這時候另乙個執行緒2也從資料庫中庫存數3,並且執行緒2進行了一些操作將庫存數變成了2,緊接著又將庫存數變成3,這時候執行緒1進行cas操作發現資料庫中仍然是3,然後執行緒1操作成功。儘管執行緒1的cas操作成功,但是不代表這個過程就是沒有問題的。

有乙個比較好的辦法可以解決aba問題,那就是通過乙個單獨的可以順序遞增的version欄位。

【優化1】

//查詢出商品資訊,version = 1

select version from items where id=1

//修改商品庫存為2

update items set quantity=2,version = 3 where id=1 and version = 2;

以上sql其實還是有一定的問題的,就是一旦高併發的時候,就只有乙個執行緒可以修改成功,那麼就會存在大量的失敗。

【優化2】

//修改商品庫存

update item

set quantity=quantity - 1

where id = 1 and quantity - 1 > 0

以上sql語句中,如果使用者下單數為1,則通過quantity - 1 > 0的方式進行樂觀鎖控制。

以上update語句,在執行過程中,會在一次原子操作中自己查詢一遍quantity的值,並將其扣減掉1。

mysql悲觀鎖和樂觀鎖

mysql鎖機制分為表級鎖和行級鎖,本文就和大家分享一下我對mysql中行級鎖中的共享鎖與排他鎖進行分享交流。共享鎖又稱為讀鎖,簡稱s鎖,顧名思義,共享鎖就是多個事務對於同一資料可以共享一把鎖,都能訪問到資料,但是只能讀不能修改。排他鎖又稱為寫鎖,簡稱x鎖,顧名思義,排他鎖就是不能與其他所並存,如乙...

悲觀鎖和樂觀鎖

1.悲觀鎖,正如其名,它指的是對資料被外界 包括本系統當前的其他事務,以及來自外部系統的事務處理 修改持保守態度,因此,在整個資料處理過程中,將資料處於鎖定狀態。悲觀鎖的實現,往往依靠資料庫提供的鎖機制 也只有資料庫層提供的鎖機制才能真正保證資料訪問的排他性,否則,即使在本系統中實現了加鎖機制,也無...

悲觀鎖和樂觀鎖

前幾天有人問了我乙個問題,說如果資料庫某些操作不用事務,那麼又需要保持資料的一致性,那麼該用什麼方法替代事務。我就想到了悲觀鎖和樂觀鎖的思想,下面我解釋一下在資料庫中的悲觀鎖和樂觀鎖 1.悲觀鎖就是把資料庫的一些操作,放在事務當中,依賴資料庫的隔離級別,實現對資料修改的封鎖,這樣做資料一致性可以保持...