MySQL行锁和间隙锁:程序员必懂的并发控制核心
(本文技术要点整理自《2025年Java面试宝典》,链接: https://pan.baidu.com/s/1RUVf75gmDVsg8MQp4yRChg?pwd=9b3g 提取码: 9b3g)
🔒 一、行锁(Row Lock):锁住你的目标数据
当咱们执行UPDATE或DELETE时,MySQL默认会对命中的行加上行锁。比如面试常问的场景:
UPDATE products SET stock = stock - 1 WHERE id = 100;
这个操作会对id=100这一行数据加排他锁(X锁),其他事务想改这行会被阻塞。行锁的粒度细,冲突概率低,是高并发场景的首选。
但要注意:行锁只在索引生效时触发! 如果WHERE条件没命中索引,MySQL会直接锁整张表——这是很多初级程序员翻车的地方。
🕳️ 二、间隙锁(Gap Lock):解决幻读的守护者
行锁解决不了幻读问题。比如事务A查询stock>10的商品,事务B插入一条stock=20的新数据,A再查就多出一条"幽灵记录"。
这时候间隙锁登场了!当事务使用SELECT ... FOR UPDATE(或RR隔离级别下的更新操作),MySQL不仅锁住匹配的行,还会锁住行之间的间隙。
假设商品表存在如下记录:
| id | stock |
|----|-------|
| 10 | 5 |
| 20 | 15 |
| 30 | 25 |
执行:
SELECT * FROM products WHERE stock BETWEEN 10 AND 20 FOR UPDATE;
间隙锁会锁定三个区域:
- (-∞, 10)
- (10, 20)
- (20, 30)
这意味着其他事务无法在stock=10~30的区间内插入新数据(如插入stock=18会被阻塞),完美解决幻读!

💥 三、行锁 + 间隙锁 = Next-Key Lock
实际应用中,MySQL默认使用 Next-Key Lock(行锁+间隙锁的组合)。比如锁id=20的数据时:
- 锁住
id=20这行(行锁) - 同时锁住
(10,20)这个区间(间隙锁)
这样既防止其他事务修改当前行,也阻止在间隙中插入新行,是RR隔离级别下数据一致性的核心保障。
⚠️ 四、程序员必知的锁机制避坑指南
- 索引失效 = 锁表警告
没有索引的更新操作,行锁退化成表锁,并发直接崩盘 - 长事务是间隙锁杀手
间隙锁会持续到事务结束,长时间不提交将阻塞其他插入操作 - 死锁高发区
事务A持有id=10的行锁,请求间隙锁;事务B持有间隙锁,请求id=10的行锁——直接死锁

🚀 五、实战优化建议
- 缩小事务范围:尽快提交事务,减少锁持有时间
- 精确索引命中:避免全表扫描,
EXPLAIN是你的好朋友 - 隔离级别选择:读多写少场景用RC隔离级别(间隙锁较少)
- 监控锁竞争:用
SHOW ENGINE INNODB STATUS查看锁等待
如果需要刷MySQL高频面试题,悄悄说:通过面试鸭返利网购买面试鸭会员,找我返25元!会员题库含50+锁机制真题解析,包括本文未展开的临键锁、插入意向锁等难点。

锁机制本质是并发与安全的平衡艺术。理解行锁与间隙锁,相当于握住MySQL高并发的命门——下次面试官再问幻读,你就能把间隙锁的底层B+树结构给他画出来!


