锁的Supremum伪记录触发时机及示例咨询(含唯一索引困惑)
关于InnoDB中Supremum伪记录的常见疑问解答
一、Supremum伪记录何时出现?
Supremum是InnoDB为实现Next-Key Lock机制,在每个索引树末尾追加的一条虚拟记录,它的排序值比索引中所有实际记录都大。以下场景会触发对它的关联处理:
- 当加锁查询的条件是大于索引中最大实际值时(比如表中最大id为90,执行
WHERE id > 100的加锁查询) - 当范围查询覆盖了索引的“右边界之外”区间时
- 执行
SELECT ... FOR UPDATE/SELECT ... LOCK IN SHARE MODE这类加锁语句,且查询逻辑触及索引末尾时
二、实操示例
假设我们有如下测试表:
CREATE TABLE test ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(20), INDEX idx_name(name) ) ENGINE=InnoDB; INSERT INTO test(name) VALUES('Alice'),('Bob'),('Charlie');
场景1:普通索引范围查询触及末尾
执行加锁查询:
SELECT * FROM test WHERE name > 'Charlie' FOR UPDATE;
此时InnoDB会对('Charlie', +∞)这个Next-Key Lock加锁,其中+∞对应的就是Supremum伪记录。如果另一个事务尝试插入name='David',会直接被阻塞,直到当前锁释放。
场景2:唯一索引查询不存在的最大值
表中当前最大id为3,执行:
SELECT * FROM test WHERE id > 3 FOR UPDATE;
同样会锁定包含Supremum伪记录的区间,此时插入新id(比如4)会被阻塞。
三、对Supremum伪记录加锁的含义
对Supremum伪记录加锁,本质是锁定索引所有实际记录之后的无限区间,核心作用是:
- 阻止其他事务往该索引的末尾插入新记录,避免破坏当前事务的查询一致性
- 保证Next-Key Lock的完整性,因为Next-Key Lock是“索引记录+相邻区间”的组合锁,Supremum就是区间的右边界终点
直白点说:就是临时禁止往这个索引的后面加新数据,直到锁被释放。
四、唯一索引单查询条件的困惑解析
很多人搞不懂:为什么唯一索引单条件查询(比如SELECT * FROM test WHERE id=5 FOR UPDATE,且id=5不存在)会涉及Supremum?这里分两种情况:
- 如果查询的是存在的唯一键值:InnoDB只会对该实际记录加Record Lock,完全不会碰Supremum
- 如果查询的是不存在的唯一键值:InnoDB会先找到该值应该插入的位置(比如表中最大id是3,查id=5时,插入位置在3之后),此时会锁定
(3, Supremum)这个区间。这么做是为了防止其他事务插入id=5的记录,避免当前事务后续操作出现数据不一致(比如之后插入id=5,再查询就会出现新数据,破坏可重复读隔离性)
举个实际场景:
事务1执行:
BEGIN; SELECT * FROM test WHERE id=5 FOR UPDATE; -- id=5不存在
此时事务2尝试执行INSERT INTO test(id) VALUES(5);会被阻塞,原因就是事务1的锁覆盖了(3, Supremum)区间,id=5落在这个区间内。这就是Supremum伪记录加锁的实际作用。
内容的提问来源于stack exchange,提问作者user19551894
相关产品推荐
相关产品推荐

