laravel mysql 锁表_Laravel中MySQL的乐观锁与悲观锁
MySQL/InnoDB的加鎖,是一個老生常談的話題。在數據庫高并發請求下,如何兼顧數據完整性與用戶體驗的敏捷性是一代又一代程序員一直在思考的問題。
樂觀鎖
樂觀鎖之所以叫樂觀,是因為這個模式不會對數據加鎖。而是對數據操作保持一種樂觀的心態,認為不會產生并發操作問題(即不會有其他線程同時對數據進行修改)。樂觀鎖查詢數據時直接進行查詢,更新時會判斷其他線程有沒有對數據進行修改,如果沒有則進行更新,反之則拒絕更新。
樂觀鎖最常用數據版本(Version)的記錄機制實現。即為數據增加一個版本標識,一般是通過為數據庫表增加一個數字類型的 “version” 字段來實現。當讀取數據時,將version字段的值一同讀出,數據每更新一次,對此version值加1。當我們提交更新的時候,判斷數據庫表對應記錄的當前版本信息與第一次取出來的version值進行比對,如果數據庫表當前版本號與第一次取出來的version值相等,則予以更新,否則認為是過期數據。
示例:
1、數據庫表三個字段,分別是id、value、versionselect id,value,version from TABLE where id = #{id}
2、每次更新表中的value字段時,為了防止發生沖突,需要這樣操作:update TABLE
set value=2,version=version+1
where id=#{id} and version=#{version}
在larave中,我們可以在數據庫維護一個lock_version字段,每次更新操作時,校驗lock_version,并在更新完成后增加lock_version的值。
悲觀鎖
悲觀鎖就比較狠了,悲觀鎖對數據做“有罪推定”。即在操作數據時,默認此操作會出現數據沖突,所以在進行每次操作時都要加鎖才能進行對相同數據的操作。一旦加鎖,不同線程同時執行時,只能有一個線程執行,其他的線程在入口處等待,直到鎖被釋放。
悲觀鎖可以由數據庫語句實現,分為共享鎖和排它鎖。
共享鎖 (lock in share mode)
共享鎖又稱讀鎖 (read lock),是讀取操作創建的鎖。其他用戶可以并發讀取數據,但任何事務都不能對數據進行修改(獲取數據上的排他鎖),直到已釋放所有共享鎖。如果事務對讀鎖進行修改操作,很可能會造成死鎖。
在Laravel中,我們在構造查詢時,可以使用 sharedLock 方法為運行語句增加一把”共享鎖“。DB::table('users')->where('votes', '>', 100)->sharedLock()->get();
上面這個查詢等價于下面這條 SQL 語句:select * from `users` where `votes` > '100' lock in share mode
注意
在查詢語句后面增加 LOCK IN SHARE MODE 后,Mysql會對查詢結果中的每行都加一個共享(讀)鎖,當沒有其他線程對查詢結果集中的任何一行使用排他鎖時,可以成功申請共享鎖,否則會被阻塞。 其他線程也可以讀取使用了共享鎖的表,而且這些線程讀取的是同一個版本的數據。
加上共享鎖后,對于update,insert,delete語句會自動加排它鎖。
排它鎖 (for update)
排他鎖又稱寫鎖(exclusive lock or writer lock)。若某個事務對某一行加上了排他鎖,只能這個事務對其進行讀寫,在此事務結束之前,其他事務不能對其進行加任何鎖,其他進程可以讀取,不能進行寫操作,需等待其釋放。排它鎖會阻塞所有的排它鎖和共享鎖。
在Laravel中,我們在構造查詢時,可以使用 lockForUpdate 方法為運行語句增加一把“排它鎖”,避免選擇行被其它共享鎖修改或刪除: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 都是鎖定性讀)。
總結
樂觀鎖適用于讀多寫少的情況,即沖突真的很少發生的時候,這樣可以省去了鎖的開銷,加大了系統的整個吞吐量。
但如果經常產生沖突,還是使用悲觀鎖更穩定、可靠一些。
參考鏈接
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的laravel mysql 锁表_Laravel中MySQL的乐观锁与悲观锁的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: centos lnmp源码安装mysql
- 下一篇: mysql 超长记录_谁记录了mysql