什么是 supremum pseudo-record?
它是MySQL InnoDB 存储引擎在索引页中定义的一条虚拟伪记录,是索引逻辑上的 “最大值边界”,并非真实存在的用户数据记录。
- 作用:标记索引页中所有记录的 “上界”,用于处理索引范围的间隙锁与 Next-Key Lock,防止幻读。
- 位置:每个索引页的末尾,和开头的
infimum pseudo-record(下界虚拟记录)对应。
🔍 为什么会出现supremum pseudo-record锁?
在可重复读(RR)隔离级别下,InnoDB 使用Next-Key Lock(记录锁 + 间隙锁)来防止幻读。当事务执行范围查询(如WHERE id > 18)或无匹配条件的查询并加锁时:
- InnoDB 会扫描索引,直到遇到
supremum pseudo-record才停止。 - 对这条虚拟记录加锁,本质是锁住了
(当前最大索引值, +∞)这个间隙。 - 这样其他事务就无法插入大于当前索引最大值的数据,避免幻读。
🧩 关键特性与影响
- 锁的本质:对
supremum pseudo-record加锁,本质是锁住索引末尾的间隙,而不是某条真实记录。 - 典型场景:
- 范围查询(如
WHERE id > ?),且查询条件包含大于表中所有记录的值; - 空表执行
SELECT ... FOR UPDATE/LOCK IN SHARE MODE,会直接锁住整个(-∞, +∞)区间; - 唯一索引冲突时的加锁流程,也会对它加锁。
- 范围查询(如
- 并发影响:
- 对
supremum pseudo-record加锁后,所有插入大于当前最大值的记录操作都会被阻塞,这也是很多 “新数据插入莫名被锁” 的常见原因。 - 尤其是使用自增主键时,新数据总是插入索引末尾,此时锁会直接阻塞所有新的
INSERT。
- 对
💡 如何排查与优化
- 定位场景:通过
performance_schema.data_locks表查看锁信息,若出现supremum pseudo-record,通常和范围查询加锁、空表加锁或唯一键冲突有关。 - 优化方案:
- 尽量使用等值查询代替范围查询(如
WHERE id = ?而非WHERE id > ?),避免触发大范围 Next-Key Lock; - 调整事务隔离级别为读已提交(RC),此时 InnoDB 会退化为仅记录锁,不再加间隙锁;
- 避免在空表上执行带锁的范围查询,或在事务中提前插入边界数据。
- 尽量使用等值查询代替范围查询(如
