# 什么是next-key lock?
什么是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就会顺便把主键也锁上