Mysql —— Gap Lock & Next-key Lock

demo table

創(chuàng)建表

create table test(
?? id int,
?? v1 int,
?? v2 int,
?? primary key(id),
?? key idx_v1(v1))
Engine=InnoDB DEFAULT CHARSET=UTF8;

該表的記錄如下:


image.png

一、Gap Lock

間隙鎖(Gap Lock)一般是針對(duì)非唯一索引而言的,test表中的v1(非唯一索引)字段值可以劃分的區(qū)間為:

(-∞,1)
(1,3)
(3,4)
(4,5)
(5,7)
(7,9)
(9, +∞)

ps:注意,gap 鎖只鎖記錄之間的范圍,不對(duì)記錄產(chǎn)生影響。

假如要更新v1=7的數(shù)據(jù)行,那么此時(shí)會(huì)在索引idx_v1對(duì)應(yīng)的值,也就是v1的值上加間隙鎖,鎖定的區(qū)間是(5,7)和(7,9)。同時(shí)找到v1=7的數(shù)據(jù)行的主鍵索引和非唯一索引,對(duì)key加上鎖。

二、Next-Key Lock

記錄鎖和間隙鎖的結(jié)合,對(duì)于InnoDB中,更新非唯一索引對(duì)應(yīng)的記錄(在這里來(lái)說(shuō)是更新v1字段的值),會(huì)加上Next-Key Lock。如果更新記錄為空,就不能加記錄鎖,只能加間隙鎖。

舉個(gè)例子(事務(wù)隔離級(jí)別為MySQL默認(rèn)的可重復(fù)讀)


image.png

問(wèn)題:
為什么TRANSACTION 2的insert操作會(huì)被阻塞,產(chǎn)生等待呢?

解釋:
這是因?yàn)門RANSACTION 2插入的v1值為6在TRANSACTION 1的鎖定區(qū)間(5,9)內(nèi)。而TRANSACTION 1插入的v1值不在TRANSACTION 2的鎖定區(qū)間(5,7)內(nèi),故可以成功插入。不僅僅insert操作, update操作也一樣會(huì)被鎖住,從而鎖等待超時(shí)。
從T2的第一個(gè)update操作也可以看出,Gap Lock之間不是互斥的。

注意:
這里需要注意,自我嘗試之后,發(fā)現(xiàn)圖中可能有些問(wèn)題。比如:在 T2 中最后的update 部分,實(shí)際上是可以成功的。如果 T2 在最后的 update 操作時(shí),由于隔離級(jí)別是 RR,T2中是沒(méi)有 v1=8的,所以并沒(méi)有收到鎖的影響。如果將 where v1=8換成 v1=1,則會(huì)等待鎖,因?yàn)門2中存在v1=1的記錄,等待鎖是因?yàn)殡m然v1=1沒(méi)有鎖,但是v1=6上有鎖,所以要等待。

三、范圍兩端記錄的鎖的問(wèn)題

加Next-key Lock的時(shí)候,并沒(méi)有鎖住間隙兩端的記錄(這里的兩端分別是5,9和5,7),那么兩端的記錄是可以更新的,但是如果更新兩端的記錄會(huì)影響到間隙鎖,那么操作會(huì)被掛起,等待間隙鎖釋放。

看以下演示:


image.png

事務(wù)2上半部分的update操作

證明:Gap Lock 鎖定的區(qū)間,如果有update操作要更新索引的值,會(huì)被鎖定。

事務(wù)2下半部分的insert操作

問(wèn)題:
為什么在左側(cè)值為4,右側(cè)值為7的時(shí)候,有時(shí)候操作會(huì)被掛起,有時(shí)候操作不會(huì)掛起呢?

解釋如下:
由于 v1 是非唯一索引,所以在 4,7 兩個(gè)值的左右也有分別。它的左右是依賴于主鍵 id 的順序來(lái)規(guī)定的。表中 v1 = 4的id為3,如果insert into test(id, v1,v2) values(0,4,3) 的記錄,則為它的左側(cè); 如果insert into test(id, v1,v2) values(6,4,3) 的記錄,則為右側(cè)。v1 = 7的同理。

當(dāng)插入左側(cè)值的時(shí)候,即插入v1=4的時(shí)候,要求插入的id值小于id=3的范圍。當(dāng)v1=4的記錄有多條的時(shí)候,插入的id值要小于其中的最大id值。則可以成功插入;
當(dāng)插入右側(cè)值的時(shí)候,即插入v1=7的時(shí)候,要求插入的id值要大于id=7的范圍。當(dāng)v1=7的記錄有多條的時(shí)候,插入的id值要大于其中的最小id值。則可以成功插入。

四、結(jié)論

  • Gap Lock 之間不是互斥的
  • Gap Lock 不僅會(huì)影響 insert,也會(huì)影響 update。因?yàn)?update 的 set 操作也會(huì)收到鎖的影響
  • Gap Lock 邊界值的左右側(cè),是先從二級(jí)索引中找到兩個(gè)邊界值,然后再用邊界值去主鍵索引樹按照主鍵順序來(lái)界定邊界值的左右側(cè)部分

搬運(yùn):MySQL InnoDB鎖機(jī)制之Gap Lock、Next-Key Lock、Record Lock解析

這部分是搬運(yùn)之后,自己又嘗試著跟了一邊demo,對(duì)原有結(jié)論的一些猜想,如果有缺失或者不對(duì)的地方,請(qǐng)?jiān)谙路搅粞?,大家一起交流,一起學(xué)習(xí),一起進(jìn)步~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容