mysql的鎖
作者:小強(qiáng)Zzz
來(lái)源:SegmentFault 思否社區(qū)
前言
mysql按鎖的范圍分三種
表級(jí)鎖:開(kāi)銷小,加鎖快;不會(huì)出現(xiàn)死鎖,鎖定粒度大,發(fā)生鎖沖突概率最高,并發(fā)度最低。
行級(jí)鎖:開(kāi)銷大,加鎖慢,會(huì)出現(xiàn)死鎖,鎖定粒度小,發(fā)生鎖沖突的概率最低,并發(fā)度最高。
頁(yè)面鎖:開(kāi)銷和加鎖時(shí)間界于表鎖和行鎖之間,會(huì)出現(xiàn)死鎖,鎖定粒度界于表鎖和行鎖之間,并發(fā)度一般。
InnoDB的加鎖模式
共享鎖(S):允許一個(gè)事務(wù)讀一行,阻止其他事務(wù)獲得相同數(shù)據(jù)的排他鎖,也叫讀鎖。
排他鎖(X):允許獲得排他鎖的事務(wù)更新數(shù)據(jù),阻止其他事務(wù)取得相同數(shù)據(jù)集的共享鎖與排他鎖,也叫寫(xiě)鎖。
同時(shí)mysql還支持與行共享鎖和行排他鎖類似的表共享鎖和表排他鎖因?yàn)殒i的粒度不同,表鎖的范圍覆蓋了行鎖的范圍,所以表鎖和行鎖會(huì)產(chǎn)生沖突,例如事務(wù)A對(duì)表中某一行數(shù)據(jù)加了行鎖,然后事務(wù)B想加表鎖,正常來(lái)說(shuō)是應(yīng)該要沖突的。要判斷是否沖突就得遍歷每一行數(shù)據(jù)了,這樣的效率不高,因此我們就有了意向表鎖。
意向鎖的主要目的是為了使得 行鎖 和 表鎖 共存,事務(wù)在申請(qǐng)行鎖前,必須先申請(qǐng)表的意向鎖,成功后再申請(qǐng)行鎖。
意向鎖分為意向共享鎖和意向排他鎖。
意向共享鎖(IS):事務(wù)打算給數(shù)據(jù)行加行共享鎖,事務(wù)在給一個(gè)數(shù)據(jù)行加共享鎖之前必須先去的該表的意向共享鎖
意向排他鎖(IX):事務(wù)打算給數(shù)據(jù)行加行排他鎖,事務(wù)在給一個(gè)數(shù)據(jù)行加排他鎖前必須先取得該表的意向排他鎖。

如果一個(gè)事務(wù)請(qǐng)求的鎖模式與當(dāng)前的鎖模式兼容,InnoDB就將請(qǐng)求的鎖授予該事務(wù),反之,如果兩者不兼容,該事務(wù)就要等待鎖釋放。
意向鎖是表級(jí)鎖,但是卻表示事務(wù)正在讀或?qū)懩骋恍杏涗洠皇钦麄€(gè)表,所以意向鎖之間不會(huì)產(chǎn)生沖突,真正的沖突在加行鎖時(shí)檢查。
加鎖方法
顯式上鎖
select * from tableName lock in share mode;//讀鎖
select * from tableName for update;//寫(xiě)鎖
解鎖
提交事務(wù)(commit)
回滾事務(wù)(rollback)
kill阻塞進(jìn)程
上讀鎖實(shí)例


因?yàn)镮nnoDB有MVCC機(jī)制(多版本并發(fā)控制),可以使用快照讀,而不會(huì)被阻塞。
InnoDB行鎖實(shí)現(xiàn)方式
行鎖(Record Lock)
間隙鎖(Gap Lock)
優(yōu)點(diǎn):解決了事務(wù)并發(fā)的幻讀問(wèn)題
不足:因?yàn)閝uery執(zhí)行過(guò)程中通過(guò)范圍查找的話,他會(huì)鎖定爭(zhēng)個(gè)范圍內(nèi)所有的索引鍵值,即使這個(gè)鍵值并不存在。
間隙鎖有一個(gè)致命的弱點(diǎn),就是當(dāng)鎖定一個(gè)范圍鍵值之后,即使某些不存在的鍵值也會(huì)被無(wú)辜的鎖定,而造成鎖定的時(shí)候無(wú)法插入鎖定鍵值范圍內(nèi)任何數(shù)據(jù)。在某些場(chǎng)景下這可能會(huì)對(duì)性能造成很大的危害。
Next-key Lock 鎖
在Repeatable Read隔離級(jí)別下,Next-key Lock 是默認(rèn)的行記錄鎖定算法。
假如teacher表中只有101條記錄,其id值分別是1-101,SQL語(yǔ)句如下
Select * from teacher where id 〉 100 for update;
樂(lè)觀鎖與悲觀鎖
樂(lè)觀鎖(Optimistic Lock):假設(shè)不會(huì)發(fā)生并發(fā)沖突,只在提交操作時(shí)檢查是否違反數(shù)據(jù)完整性。樂(lè)觀鎖不能解決臟讀的問(wèn)題。
悲觀鎖,就是很悲觀,每次去拿數(shù)據(jù)的時(shí)候都認(rèn)為別人會(huì)修改,所以每次在拿數(shù)據(jù)的時(shí)候都會(huì)上鎖,這樣別人想拿這個(gè)數(shù)據(jù)就會(huì)被阻塞直到它拿到鎖。傳統(tǒng)的關(guān)系型數(shù)據(jù)庫(kù)里邊就用到了很多這種鎖機(jī)制,比如行鎖,表鎖等,都是在做操作之前先上鎖。
總結(jié)
鎖和多版本數(shù)據(jù)(MVCC)是 InnoDB 實(shí)現(xiàn)一致性讀和四種隔離隔離級(jí)別的手段。
因此,在不同的隔離級(jí)別下,InnoDB 處理 SQL 時(shí)需要的鎖是不同的。

