間隙鎖鎖的內(nèi)容:鎖定兩個值之間的空隙
間隙鎖產(chǎn)生的原因:為了解決幻讀問題
鎖是加在對應(yīng)的索引上的贿堰,訪問到對應(yīng)的索引澎蛛,才會向?qū)?yīng)的索引上加鎖
前提:可重復(fù)度級別
描述一下幻讀:
產(chǎn)生的前提條件:在可重復(fù)度隔離級別下,使用“當(dāng)前讀”出現(xiàn)的一種現(xiàn)象
現(xiàn)象:能夠看到其他事務(wù)插入的最新數(shù)據(jù)
描述一下當(dāng)前讀和快照讀:
當(dāng)前讀:讀取最新版本的數(shù)據(jù)威根,并對讀取的記錄加鎖(間隙鎖+行鎖)(例如 select ... for update)
快照讀:看不到其他事務(wù)插入的新數(shù)據(jù)(在執(zhí)行select操作時生成一張快照,不是開啟事務(wù)的時候视乐,生成快照之后的變動都無感知)
當(dāng)前讀的方法是:for update洛搀,in share mode,update佑淀,delete留美,insert 操作
間隙鎖+行鎖(next-key lock)(前開后閉區(qū)間)
加鎖的規(guī)則
原則 1:加鎖的基本單位是 next-key lock。希望你還記得伸刃,next-key lock 是前開后閉區(qū)間谎砾。
原則 2:查找過程中訪問到的對象才會加鎖。
優(yōu)化 1:索引上的等值查詢捧颅,給唯一索引加鎖的時候景图,next-key lock 退化為行鎖。(需要命中對應(yīng)的行)
優(yōu)化 2:索引上的等值查詢碉哑,向右遍歷時且最后一個值不滿足等值條件的時候挚币,next-key lock 退化為間隙鎖。
一個 bug:唯一索引上的范圍查詢會訪問到不滿足條件的第一個值為止扣典。
對未命中索引的查詢妆毕,例如d沒有索引
image.png
select * from t2 where d = 100 for update。此時間隙鎖會鎖住全表
limit語句會縮小加鎖范圍贮尖,在找到limit指定的條數(shù)之后笛粘,不會再繼續(xù)遍歷
next-key lock:加鎖的過程
首先是先加間隙鎖,然后才加行鎖
對非索引字段的加間隙鎖湿硝,會導(dǎo)致鎖表
order by *** desc 會倒序遍歷
sql語句分析
表結(jié)構(gòu)
CREATE TABLE `t2` (
`id` int(11) NOT NULL,
`c` int(11) DEFAULT NULL,
`d` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `c` (`c`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
BEGIN;
INSERT INTO `t2` VALUES (0, 0, 0);
INSERT INTO `t2` VALUES (5, 5, 5);
INSERT INTO `t2` VALUES (10, 10, 10);
INSERT INTO `t2` VALUES (15, 15, 15);
INSERT INTO `t2` VALUES (20, 20, 20);
INSERT INTO `t2` VALUES (25, 25, 25);
COMMIT;
SET FOREIGN_KEY_CHECKS = 1;
select * from t2 where c >= 15 and c <= 20 order by c desc lock in share mode;
對sql進行next-key lock分析
order by c desc 說明需要倒序查找
首先命中20薪前,增加next-key lock (15,20]
c=20由于優(yōu)化2,向右遍歷至第一個不符合不滿足為止并退化為間隙鎖 (20,25)
c>15关斜,繼續(xù)向前查找找到不滿足為止示括,訪問到c=10
由于原則2,因為10被訪問到蚤吹,所以也需要加上next-key lock例诀,(5,10]
最終推出上鎖范圍 (5,25)
select * from t2 where c >= 15 and c <= 20 lock in share mode;
對sql進行next-key lock分析
首先命中15随抠,增加next-key lock (10,15]
然后繼續(xù)遍歷裁着,(15,20]
由于等值查詢 c = 20,優(yōu)化2,向右遍歷至第一個不符合不滿足為止并退化為間隙鎖 (20,25)
最終推出上鎖范圍 (10,25)