什么是next-key lock?
在RR(可重復讀,mysql默認事務隔離級別)隔離級別下,mysql 通過next-key lock解決了大部分幻讀的場景。
next-key lock 由行鎖和間隙鎖組成。
比如(5, 10) 和 加在10上的行鎖組成(5,10]的next-key lock
怎么加next-key lock?
- 加鎖的基本單位是next-key lock, 前開后閉區間;
- 查找過程訪問的對象才會加鎖
- 優化1:索引上的等值查詢,唯一索引加鎖會退化為行鎖
- 優化2:索引上的等值查詢,向右遍歷且最后一個值不滿足等值條件時候,next-key lock
退化為間隙鎖 - mysql 5.xxx <= 5.7.24 和 8.0系列 <= 8.0.13 的 版本,當給唯一索引加鎖時,會
訪問到不滿足條件的第一個值為止。
等值查詢:指的是搜索索引樹的過程。
例子
select * from t where id > 9 and id < 12 order by id desc for update;
加鎖 (0, 5], (5, 10], (10, 15)
加鎖過程: 第一個滿足條件的是id=10,加next-key lock (5, 10],
id=10是索引樹上存在的記錄,繼續往右側查詢,根據優化2,加間隙鎖(10, 15)。
根據order by id desc,然后往左遍歷,遇到5, 加next-key lock
(0, 5], 因為5已經不滿足id < 9條件了,停止遍歷
select * from t where id > 9 and id < 12 order by id for update;
加鎖 (5, 10], (10 15]
加鎖過程:跟上面一樣,第一個滿足條件的是id=10,加next-key lock (5, 10],
往右遍歷,遇到15,加next-key lock (10, 15), 不滿足id < 12條件了,停止遍歷。
select * from t where c > 5 lock in share
加鎖:(5,10]、(10,15]、(15,20]、(20,25]和 (25,supremum]
加鎖過程:從索引樹上遍歷,第一個遇到10,加(5, 10], 然后,15,20,25。最后的25加的是
(25, supremum], supremum 代表正無窮。
lock in share mode 對比 for update
select id from t where c=5 lock in share mode;
加鎖:(0, 5], (5, 10)
加鎖過程:在索引樹上找到c=5,加next-key lock (0,5], 由於不是c不是唯一索引,還需要繼續往右
查找,找到10,加next-key lock (5,10],根據優化2,10不滿足等值條件,退化為(5,10)。因此查詢剛好被索引覆蓋了,主鍵不用鎖上,
因此主鍵索引5是可以更新的,但是for update就會順便把主鍵也鎖上