間隙鎖和行鎖加鎖規(guī)則

表和數(shù)據(jù)

CREATE TABLE `t` (
  `id` int(11) NOT NULL,
  `c` int(11) DEFAULT NULL,
  `d` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `c` (`c`)
) ENGINE=InnoDB;

insert into t values(0,0,0),(5,5,5),
(10,10,10),(15,15,15),(20,20,20),(25,25,25);

規(guī)則總結(這個規(guī)則只限于截止到現(xiàn)在的最新版本骂维,即 5.x 系列 <=5.7.24,8.0 系列 <=8.0.13哮兰。):
原則 1:加鎖的基本單位是 next-key lock毛萌。希望你還記得,next-key lock 是前開后閉區(qū)間喝滞。
原則 2:查找過程中訪問到的對象才會加鎖阁将。
優(yōu)化 1:索引上的等值查詢,給唯一索引加鎖的時候右遭,next-key lock 退化為行鎖做盅。
優(yōu)化 2:索引上的等值查詢,向右遍歷時且最后一個值不滿足等值條件的時候窘哈,next-key lock 退化為間隙鎖吹榴。
一個 bug:唯一索引上的范圍查詢會訪問到不滿足條件的第一個值為止。

案例一:等值查詢間隙鎖


等值查詢間隙鎖
  • 根據(jù)原則 1滚婉,加鎖單位是 next-key lock图筹,session A 加鎖范圍就是 (5,10];
  • 同時根據(jù)優(yōu)化 2让腹,這是一個等值查詢 (id=7)远剩,而 id=10 不滿足查詢條件,next-key lock 退化成間隙鎖骇窍,因此最終加鎖的范圍是 (5,10)瓜晤。

案例二:非唯一索引等值鎖


非唯一索引等值鎖

根據(jù)原則1,優(yōu)化2腹纳,鎖的范圍是(0,5],(5,10)活鹰,但是根據(jù)原則2,只有訪問到的對象才加鎖只估,這個查詢使用了覆蓋索引,并不訪問主鍵索引着绷,所以主鍵上沒加鎖蛔钙。
需要注意,在這個例子中荠医,lock in share mode 只鎖覆蓋索引吁脱,但是如果是 for update 就不一樣了桑涎。 執(zhí)行 for update 時,系統(tǒng)會認為你接下來要更新數(shù)據(jù)兼贡,因此會順便給主鍵索引上滿足條件的行加上行鎖攻冷。

案例三:主鍵索引范圍鎖


主鍵索引范圍鎖
  • 開始執(zhí)行的時候,要找到第一個 id=10 的行遍希,因此本該是 next-key lock(5,10]等曼。 根據(jù)優(yōu)化 1, 主鍵 id 上的等值條件凿蒜,退化成行鎖禁谦,只加了 id=10 這一行的行鎖。
  • 范圍查找就往后繼續(xù)找废封,找到 id=15 這一行停下來州泊,因此需要加 next-key lock(10,15]。
    首次 session A 定位查找 id=10 的行的時候漂洋,是當做等值查詢來判斷的遥皂,而向右掃描到 id=15 的時候,用的是范圍查詢判斷

案例四:非唯一索引范圍鎖


非唯一索引范圍鎖

這次 session A 用字段 c 來判斷刽漂,加鎖規(guī)則跟案例三唯一的不同是:在第一次用 c=10 定位記錄的時候演训,索引 c 上加了 (5,10] 這個 next-key lock 后,由于索引 c 是非唯一索引爽冕,沒有優(yōu)化規(guī)則仇祭,也就是說不會蛻變?yōu)樾墟i,因此最終 sesion A 加的鎖是颈畸,索引 c 上的 (5,10] 和 (10,15] 這兩個 next-key lock乌奇。

案例五:唯一索引范圍鎖 bug


唯一索引范圍鎖 bug
  • session A 是一個范圍查詢,按照原則 1 的話眯娱,應該是索引 id 上只加 (10,15] 這個 next-key lock礁苗,并且因為 id 是唯一鍵,所以循環(huán)判斷到 id=15 這一行就應該停止了徙缴。
  • 但是實現(xiàn)上试伙,InnoDB 會往前掃描到第一個不滿足條件的行為止,也就是 id=20于样。而且由于這是個范圍掃描疏叨,因此索引 id 上的 (15,20] 這個 next-key lock 也會被鎖上。改成select * from t where id>10 and id<15 for update;則只會加new-key lock(10,15]

案例六:非唯一索引上存在"等值"的例子
表中插入一條mysql> insert into t values(30,10,30);



這時穿剖,session A 在遍歷的時候蚤蔓,先訪問第一個 c=10 的記錄。同樣地糊余,根據(jù)原則 1秀又,這里加的是 (c=5,id=5) 到 (c=10,id=10) 這個 next-key lock单寂。
然后,session A 向右查找吐辙,直到碰到 (c=15,id=15) 這一行宣决,循環(huán)才結束。根據(jù)優(yōu)化 2昏苏,這是一個等值查詢尊沸,向右查找到了不滿足條件的行,所以會退化成 (c=10,id=10) 到 (c=15,id=15) 的間隙鎖捷雕。

案例七:limit 語句加鎖



索引 c 上的加鎖范圍變成了從(c=5,id=5) 到(c=10,id=30) 這個前開后閉區(qū)間椒丧,如下圖所示:


案例八:一個死鎖的例子


死鎖
  • session A 啟動事務后執(zhí)行查詢語句加 lock in share mode,在索引 c 上加了 next-key lock(5,10] 和間隙鎖 (10,15)救巷;
  • session B 的 update 語句也要在索引 c 上加 next-key lock(5,10] 壶熏,進入鎖等待;
  • 然后 session A 要再插入 (8,8,8) 這一行浦译,被 session B 的間隙鎖鎖住棒假。由于出現(xiàn)了死鎖,InnoDB 讓 session B 回滾精盅。
    session B的行鎖c=10和session A有沖突帽哑,所以死鎖

在讀提交情況下,語句執(zhí)行過程中加上的行鎖叹俏,在語句執(zhí)行完成后妻枕,就要把“不滿足條件的行”上的行鎖直接釋放了,不需要等到事務提交粘驰。

費解的問題



1.由于是 order by c desc屡谐,第一個要定位的是索引 c 上“最右邊的”c=20 的行,所以會加上間隙鎖 (20,25) 和 next-key lock (15,20]蝌数。
2.在索引 c 上向左遍歷愕掏,要掃描到 c=10 才停下來,所以 next-key lock 會加到 (5,10]顶伞,這正是阻塞 session B 的 insert 語句的原因饵撑。
3.在掃描過程中,c=20唆貌、c=15滑潘、c=10 這三行都存在值,由于是 select *锨咙,所以會在主鍵 id 上加三個行鎖众羡。

參考:https://time.geekbang.org/column/article/75659

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市蓖租,隨后出現(xiàn)的幾起案子粱侣,更是在濱河造成了極大的恐慌,老刑警劉巖蓖宦,帶你破解...
    沈念sama閱讀 221,888評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件齐婴,死亡現(xiàn)場離奇詭異,居然都是意外死亡稠茂,警方通過查閱死者的電腦和手機柠偶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,677評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來睬关,“玉大人诱担,你說我怎么就攤上這事〉绲” “怎么了蔫仙?”我有些...
    開封第一講書人閱讀 168,386評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長丐箩。 經(jīng)常有香客問我摇邦,道長,這世上最難降的妖魔是什么屎勘? 我笑而不...
    開封第一講書人閱讀 59,726評論 1 297
  • 正文 為了忘掉前任施籍,我火速辦了婚禮,結果婚禮上概漱,老公的妹妹穿的比我還像新娘丑慎。我一直安慰自己,他們只是感情好瓤摧,可當我...
    茶點故事閱讀 68,729評論 6 397
  • 文/花漫 我一把揭開白布竿裂。 她就那樣靜靜地躺著,像睡著了一般姻灶。 火紅的嫁衣襯著肌膚如雪铛绰。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,337評論 1 310
  • 那天产喉,我揣著相機與錄音捂掰,去河邊找鬼。 笑死曾沈,一個胖子當著我的面吹牛这嚣,可吹牛的內容都是我干的。 我是一名探鬼主播塞俱,決...
    沈念sama閱讀 40,902評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼姐帚,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了障涯?” 一聲冷哼從身側響起罐旗,我...
    開封第一講書人閱讀 39,807評論 0 276
  • 序言:老撾萬榮一對情侶失蹤膳汪,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后九秀,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體遗嗽,經(jīng)...
    沈念sama閱讀 46,349評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,439評論 3 340
  • 正文 我和宋清朗相戀三年鼓蜒,在試婚紗的時候發(fā)現(xiàn)自己被綠了痹换。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,567評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡都弹,死狀恐怖娇豫,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情畅厢,我是刑警寧澤冯痢,帶...
    沈念sama閱讀 36,242評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站或详,受9級特大地震影響系羞,放射性物質發(fā)生泄漏。R本人自食惡果不足惜霸琴,卻給世界環(huán)境...
    茶點故事閱讀 41,933評論 3 334
  • 文/蒙蒙 一椒振、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧梧乘,春花似錦澎迎、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,420評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至仁堪,卻和暖如春哮洽,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背弦聂。 一陣腳步聲響...
    開封第一講書人閱讀 33,531評論 1 272
  • 我被黑心中介騙來泰國打工鸟辅, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人莺葫。 一個月前我還...
    沈念sama閱讀 48,995評論 3 377
  • 正文 我出身青樓匪凉,卻偏偏與公主長得像,于是被迫代替她去往敵國和親捺檬。 傳聞我的和親對象是個殘疾皇子再层,可洞房花燭夜當晚...
    茶點故事閱讀 45,585評論 2 359

推薦閱讀更多精彩內容

  • 我們都知道事務的幾種性質,數(shù)據(jù)庫為了維護這些性質,尤其是一致性和隔離性聂受,一般使用加鎖這種方式蒿秦。同時數(shù)據(jù)庫又是個高并...
    CodeKing2017閱讀 625評論 0 7
  • 背景 MySQL/InnoDB的加鎖分析,一直是一個比較困難的話題饺饭。我在工作過程中渤早,經(jīng)常會有同事咨詢這方面的問題。...
    MakeACoder閱讀 615評論 0 3
  • MySQL 加鎖處理分析 12月 13th, 2013 發(fā)表評論 | Trackback 1 背景 1 1.1 M...
    10xjzheng閱讀 4,600評論 3 7
  • 1 最近在讀王興的傳記悴灵,卻意外對王背后的的另外一個王感興趣扛芽。 他,就是王慧文积瞒,媒體筆下的老王川尖,美團人口中的慧文哥。...
    tanglewood閱讀 4,397評論 1 0
  • 每天茫孔,我們都在路上叮喳,走著,走著缰贝。有的人抬頭望向天空馍悟,有的人低頭玩著手機,有的人就是默默的走著剩晴。我們有個共同的特點锣咒,...
    wowwowwowsky閱讀 381評論 0 0