聊一聊MySQL的共享鎖和獨占鎖
多個事務同時更新一行數據,都會加鎖,然后排隊等待,必須一個事務執行完畢提交了,釋放鎖,才能喚醒下一個事務繼續執行。那這多個事務運行時,加的啥鎖?
是X鎖,Exclude獨占鎖,當有一個事務加了獨占鎖,此時其他事務再想更新這行數據,都要加獨占鎖,但只能暫時生成獨占鎖并在后面等待。
當有人在更新數據時,其他事務可以讀取這行數據嗎?需要加鎖嗎?
不用,因為默認情況下,有人在更新數據時,然后你要去讀取,直接默認就是開啟MVCC。即此時對一行數據的讀、寫兩個操作默認不會加鎖互斥,因為MySQL的MVCC就是為此設計,避免頻繁加鎖互斥。
此時你讀取數據,完全可以根據你的ReadView,去undo log版本鏈條里找個你能讀的版本,而完全不用顧慮別人是否在更新。
就算你真的等他更新完畢并提交了,基于MVCC,你也讀不到他更新的值!因為ReadView機制不允許,所以你默認情況下的讀,完全無需加鎖,不需要去關心其他事務的更新加鎖問題,直接基于MVCC讀某個快照即可。
萬一要是你在執行查詢操作時,偏想加鎖呢?
也可以滿足你,MySQL支持共享鎖,S鎖,語法如下:
select * from table lock in share mode
在查詢語句后面加上lock in share mode,意思就是查詢的時候對一行數據加共享鎖。若此時有別的事務在更新這行數據,已經加了獨占鎖,此時你的共享鎖還能加嗎?
若你先加了共享鎖,然后別人來更新要加獨占鎖行嗎?
當然不行了,此時鎖互斥,他只能等待。
若你在加共享鎖時,別人也加共享鎖呢?
可以的,你們倆都可加共享鎖,共享鎖和共享鎖不互斥。
所以更新數據時,必然加獨占鎖,獨占鎖和獨占鎖互斥,此時別人不能更新; 但若此時你要查詢,默認不加鎖,走MVCC讀快照版本,但你查詢是可以手動加共享鎖的,共享鎖和獨占鎖互斥,共享鎖和共享鎖不互斥。
一般開發業務系統的時候,其實你查詢主動加共享鎖很少見,數據庫行鎖雖然實用, 但一般不會在數據庫層面做復雜的手動加鎖,反而會用基于redis/zookeeper的分布式鎖來控制業務系統的鎖邏輯。
查詢操作還能加互斥鎖:
select * from table for update
我查出來數據以后還要更新,此時我加獨占鎖了,其他閑雜人等,都不要更新這數據了!
一旦你查詢時加獨占鎖,在你事務提交前,任何人都不能更新數據,只能你在本事務里更新數據,等你提交了,別人才能再更新數據。
總結
本文描述了默認情況下更新數據的獨占鎖,默認情況下查詢數據的mvcc機制讀快照,然后通過查詢加共享鎖和獨占鎖的方式,共享鎖和獨占鎖之間的互斥規則。