之前一直对间隙锁的锁定范围很迷糊,感觉不可控,最近又看了下相关文章,再加上测试,发现间隙锁真的只是顾名思义,间隙锁就是间隙锁。
MySQL 版本:8.0.28
先说结论,间隙锁只会在语句用到的索引上添加,不管这个是辅助索引还是聚集索引。所以会有如下的场景:
- 使用主键,等值查询,不会加间隙锁
- 使用主键,范围查询,加间隙锁
- 使用唯一索引,等值查询,不加间隙锁
- 使用唯一索引,范围查询,在唯一索引上加间隙锁
- 普通索引,等值查询,加间隙锁
- 普通索引,范围查询,加间隙锁
- 普通索引,会对索引的全部范围加间隙锁,从而无法对这个表再进行修改
举个例子,有如下的 student 表
表中有4条记录,
则,对于age字段的索引 idx_age 而言,其值包括如下
age id
12 3
16 7
23 5
43 10
在辅助索引中,值的排序是先根据索引字段,然后再按主键排序,所以上面的顺序就是该索引值的顺序。所以对于 (16, 7) 这一值而言,他的左右间隙分别是 (12, 3)和(23, 5),若有查询语句如下
SELECT * FROM student WHERE age = 16 FOR UPDATE
则 (12, 3) < x <= (23, 5) 的范围内都会被加锁,也就意味着,如下的组合是无法写入的
age = 12, id = 4
age = 12, id = 100
age = 20, id = 54
.....
具体加的锁可以通过查询 performance_schema.data_locks 表,如下所示
可以很清晰的看到,加的锁包括
- 意向排他锁
- 主键索引的行锁
- 辅助索引的间隙锁