如何理解临键锁Next-Key Lock_行锁与间隙锁的组合原理解析
临键锁锁定的是左开右闭区间,如对索引值20加锁即锁住(10,20],包含记录20及前一索引间隙;仅作用于被扫描的索引范围,且在REPEATABLE READ下启用。临键锁到底锁了哪块数据?临键锁不是新锁类型,而是 Record Lock(行锁)和 Gap Lock(间隙锁)的自动组合,只在 REPEATABLE READ 隔离级别下默认启用。它锁定的是一个「左开右闭」区间:比如索引值为 10、20、30,那么对 20 加临键锁,实际锁住的是 (10, 20] —— 包含记录 20 本身,也包含它前面那个“空档”。关键点在于:这个“前面”是按索引顺序算的,不是物理位置;且只作用于**被扫描到的索引范围**,不是整张表。如果你 SELECT * FROM t WHERE id = 20 FOR UPDATE,且 id 是主键 → InnoDB 会优化成纯行锁(Record Lock),不加间隙部分但如果是 SELECT * FROM t WHERE id > 15 AND id → 即使只有 id=20 一条匹配,也会锁住 <code>(10, 20] 和 (20, 30] 两个临键区间如果查询没走索引(比如 WHERE name = 'xxx' 且 name 无索引),InnoDB 可能退化为全表扫描+表级锁,临键锁机制完全失效为什么有时 update 会被莫名其妙卡住?这是临键锁最典型的副作用:你以为只改一行,其实锁了一片区域,别人往“缝隙里”插数据就被堵住了。常见卡顿场景:T1 执行 SELECT * FROM users WHERE age BETWEEN 22 AND 28 FOR UPDATE → 锁住所有 age 在 [22,28] 的记录 + 它们前后的间隙,比如 (20, 22]、(22, 28]、(28, 30]T2 尝试 INSERT INTO users (age, name) VALUES (25, 'new') → 被阻塞,因为 25 落在已锁的 (22, 28] 区间内T3 尝试 INSERT INTO users (age, name) VALUES (21, 'old') → 同样被阻塞,因 21 落在 (20, 22] 内这不是 bug,是 InnoDB 主动防止幻读的设计。但业务上若频繁范围查询 + 并发插入,就容易形成隐性锁竞争。 知元AI AI智能语音聊天 对讲问答 AI绘画 AI写作 AI创作助手工具
