Laravel中悲觀鎖 & 樂觀鎖的使用


【名詞解釋】

悲觀鎖(Pessimistic Lock),顧名思義,就是很悲觀,每次去拿數據的時候都認為別人會修改,所以每次在拿數據的時候都會上鎖,這樣別人想拿這個數據就會阻塞直到它拿到鎖。傳統的關系型數據庫里邊就用到了很多這種鎖機制,比如行鎖、表鎖、讀鎖、寫鎖等,都是在做操作之前先上鎖。

樂觀鎖(Optimistic Lock),顧名思義,就是很樂觀,每次去拿數據的時候都認為別人不會修改,所以不會上鎖,但是在更新的時候會判斷一下在此期間別人有沒有去更新這個數據,可以使用版本號等機制實現。樂觀鎖適用於多讀的應用類型,這樣可以提高吞吐量,像數據庫如果提供類似於 write_condition 機制的其實都是提供的樂觀鎖。

【如何使用】

下面我們看下悲觀鎖和樂觀鎖在 Laravel 中的使用:

悲觀鎖使用
Laravel 查詢構建器提供了一些方法幫助你在 select 語句中實現“悲觀鎖”。可以在查詢中使用 sharedLock 方法從而在運行語句時帶一把”共享鎖“。共享鎖可以避免被選擇的行被修改直到事務提交:

DB::table('users')->where('votes', '>', 100)->sharedLock()->get();

上面這個查詢等價於下面這條 SQL 語句:

select * from `users` where `votes` > '100' lock in share mode;

此外你還可以使用 lockForUpdate 方法。“for update”鎖避免選擇行被其它共享鎖修改或刪除:

DB::table('users')->where('votes', '>', 100)->lockForUpdate()->get();

上面這個查詢等價於下面這條 SQL 語句:

select * from `users` where `votes` > '100' for update;

for update 與 lock in share mode 都是用於確保被選中的記錄值不能被其它事務更新(上鎖),兩者的區別在於 lock in share mode 不會阻塞其它事務讀取被鎖定行記錄的值,而 for update 會阻塞其他鎖定性讀對鎖定行的讀取(非鎖定性讀仍然可以讀取這些記錄,lock in share mode 和 for update 都是鎖定性讀)。

這么說比較抽象,我們舉個計數器的例子:在一條語句中讀取一個值,然后在另一條語句中更新這個值。使用 lock in share mode 的話可以允許兩個事務讀取相同的初始化值,所以執行兩個事務之后最終計數器的值+1;而如果使用 for update 的話,會鎖定第二個事務對記錄值的讀取直到第一個事務執行完成,這樣計數器的最終結果就是+2了。

樂觀鎖使用
樂觀鎖,大多是基於數據版本 ( Version )記錄機制實現。何謂數據版本?即為數據增加一個版本標識,在基於數據庫表的版本解決方案中,一般是通過為數據庫表增加一個 “version” 字段來實現。

讀取出數據時,將此版本號一同讀出,之后更新時,對此版本號加一。此時,將提交數據的版本數據與數據庫表對應記錄的當前版本信息進行比對,如果提交的數據版本號大於數據庫表當前版本號,則予以更新,否則認為是過期數據。

【使用總結】
兩種鎖各有優缺點,不可認為一種好於另一種,像樂觀鎖適用於寫比較少的情況下,即沖突真的很少發生的時候,這樣可以省去了鎖的開銷,加大了系統的整個吞吐量。但如果經常產生沖突,上層應用會不斷的進行重試,這樣反倒是降低了性能,所以這種情況下用悲觀鎖就比較合適。

 

參考文章:http://www.hu-rong.com/article/362


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM