mysql临键锁是innodb引擎为了实现可重复读隔离级别并防止幻读而引入的一种组合锁,它同时包含记录锁和间隙锁,锁定某条索引记录及其前面的间隙。在日常开发中,当我们执行范围查询并加锁时,经常就会触发表里的临键锁。

什么是mysql临键锁
临键锁英文叫next-key lock,是mysql innodb在默认隔离级别(可重复读)下使用的锁类型。它由两部分组成:
- 记录锁:锁住具体的索引行,防止其他事务修改或删除。
- 间隙锁:锁住两条记录之间的空隙,防止其他事务往里插入新数据。
所以临键锁锁定的范围是“左开右闭”的区间,比如索引值为10的记录上的临键锁,会锁住(前一条记录, 10]这个区间。
临键锁的加锁规则
在innodb中,如果查询使用了索引并且是范围查询或者等值查询命中了唯一索引以外的场景,通常会加临键锁。简单总结如下:
| 查询类型 | 索引情况 | 加锁方式 |
|---|---|---|
| 等值查询 | 唯一索引命中 | 仅记录锁 |
| 等值查询 | 普通索引命中 | 临键锁 |
| 范围查询 | 任意索引 | 临键锁 |
代码示例说明
下面用一个简单的表和事务来演示临键锁的效果。假设有表t,id是普通索引:
-- 事务A begin; select * from t where id >= 10 and id < 20 for update; -- 此时事务A对id在[10, 20]及相关间隙加了临键锁 -- 事务B执行下面语句会被阻塞 -- insert into t(id, name) values(15, 'test');
在上面代码中,由于使用了范围查询并加锁,innodb会对满足条件的记录及间隙加临键锁,其他事务在锁范围内插入数据就会被阻塞。
为什么需要临键锁
临键锁的核心目的是解决幻读问题。如果不锁间隙,别的事务插入了符合条件的新行,当前事务再次查询就会出现之前没看到的数据。通过临键锁把记录和间隙一起锁住,就保证了同一事务内多次查询范围结果一致。
使用注意点
- 临键锁只在可重复读及以下隔离级别生效,读已提交级别会禁用间隙锁。
- 如果查询没走索引,innodb会锁全表的所有间隙和记录,并发性能很差。
- 死锁常因不同事务加临键锁顺序交叉引起,写sql时要注意访问顺序。
临键锁不是单独存在的锁对象,而是记录锁加间隙锁的组合行为,理解这一点有助于看懂show engine innodb status里的锁信息。
总结
mysql临键锁是innodb防止幻读的重要机制,搞清它的加锁区间和触发条件,能帮我们写出更安全的高并发sql,也更容易定位线上锁等待和死锁问题。
mysql临键锁next_key_lock修改时间:2026-07-27 15:42:20