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