如何通过优化SQL范围查询和索引设计,有效避免MySQL中Range查询引发的间隙锁冲突?
- 内容介绍
- 文章标签
- 相关推荐
本文共计998个文字,预计阅读时间需要4分钟。
MySQL在可重复读(RR)隔离级别下,使用`SELECT ... FOR UPDATE`或带有范围条件的`UPDATE`语句时,InnoDB不仅锁定目标记录,还会锁定间隔(gap)——即尚未存在于记录中的索引区间。例如,主键是`id`,现有记录为`9, 10, 15, 20, 25`,执行`UPDATE t SET x=1 WHERE id BETWEEN 10 AND 20`,InnoDB实际加锁区间为`(9, 25)`。其中,`21`这个不存在于记录中的值就会落在间隔中,被锁定,导致其他事务插入`id=21`的记录被阻塞。
用 SELECT ... LOCK IN SHARE MODE 能避免间隙锁吗?
不能。只要语句走的是**范围扫描 + 当前行锁模式开启**(如 RR 隔离级),InnoDB 就会加间隙锁或 next-key 锁,和你是 FOR UPDATE 还是 LOCK IN SHARE MODE 无关。唯一能绕过间隙锁的方式是:让查询退化为**唯一等值查找**,且该值存在。
本文共计998个文字,预计阅读时间需要4分钟。
MySQL在可重复读(RR)隔离级别下,使用`SELECT ... FOR UPDATE`或带有范围条件的`UPDATE`语句时,InnoDB不仅锁定目标记录,还会锁定间隔(gap)——即尚未存在于记录中的索引区间。例如,主键是`id`,现有记录为`9, 10, 15, 20, 25`,执行`UPDATE t SET x=1 WHERE id BETWEEN 10 AND 20`,InnoDB实际加锁区间为`(9, 25)`。其中,`21`这个不存在于记录中的值就会落在间隔中,被锁定,导致其他事务插入`id=21`的记录被阻塞。
用 SELECT ... LOCK IN SHARE MODE 能避免间隙锁吗?
不能。只要语句走的是**范围扫描 + 当前行锁模式开启**(如 RR 隔离级),InnoDB 就会加间隙锁或 next-key 锁,和你是 FOR UPDATE 还是 LOCK IN SHARE MODE 无关。唯一能绕过间隙锁的方式是:让查询退化为**唯一等值查找**,且该值存在。

