极客时间mysql实战45讲里面的丁奇老师总结的这个规则中,包含了两个“原则”、两个“优化”和一个“bug”:
- 原则1:加锁的基本单位是next-key lock。希望你还记得,next-key lock是前开后闭区间。
- 原则2:查找过程中访问到的对象才会加锁。
- 优化1:索引上的等值查询,给唯一索引加锁的时候,next-key lock退化为行锁。
- 优化2:索引上的等值查询,向右遍历时且最后一个值不满足等值条件的时候,next-key lock退化为间隙锁。
- 一个bug:唯一索引上的范围查询会访问到不满足条件的第一个值为止。
这个规则在很多范例让我很难推导出正确的加锁结果,所以我按照自己的理解,总结了一下面的规则
查看锁
查performance_schema.data_locks表
S、X表示next-key lock
S,REC_NOT_GAP和X,REC_NOT_GAP表示行锁
S,GAP和X,GAP表示间隙锁
非唯一索引的等值查询
条件对应的记录不存在,第一个不满足的记录的记录加gap lock
条件对应的记录存在,满足条件的记录加next-key lock,直到第一个不满足的记录加gap lock,满足条件的主键记录加行锁
唯一索引的等值查询
条件对应的记录不存在,第一个不满足的记录的记录加gap lock
条件对应的记录存在,满足条件的记录加行锁
非唯一索引的范围查询
左边界找到第一个符合条件的记录,加next-key lock
右边界找到第一个不符合条件的记录,加next-key lock
其它记录都加next-key lock,且满足条件的主键记录也会行锁
唯一索引的范围查询
左边界找到第一个符合条件的记录,加next-key lock,例外情况条件为>=,且参数对应的记录存在,这条记录加行锁
例外范例 id>=10,10这条记录存在,那10这条记录加行锁
右边界找到第一个不符合条件的记录,加gap lock,例外情况是条件为<=,且参数对应的记录存在,这条记录next-key lock
例外范例 id<=20,20这条记录存在,那20这条记录加next-key lock
order by key desc
范围查询经过逆向排序时,唯一索引和非唯一索引规则一样
右边界向右第一个不满足条件的记录加gaplock
左边界向左第一个不满足条件的记录加next-key lock
其它记录都加next-key lock