mysql间隙锁:深度解析与高频面试题破解指南
2025年Java面试宝典重磅来袭!
立即获取:https://pan.baidu.com/s/1RUVf75gmDVsg8MQp4yRChg?pwd=9b3g (提取码: 9b3g)
什么是MySQL间隙锁?
间隙锁(Gap Lock)是InnoDB引擎特有的锁机制,专门锁定索引记录之间的间隙。比如你的表有id为1、3、5的记录,当你用WHERE id=2查询时,MySQL不仅会锁定不存在的2这条"虚拟记录",还会锁定(1,3)这个区间,防止其他事务插入新数据。这种锁在Repeatable Read隔离级别下尤为关键。

间隙锁的三大核心作用
- 解决幻读问题:当事务A执行
SELECT * WHERE id>10时,间隙锁会锁住10以后的所有间隙,阻止事务B插入id=11的新数据 - 保证范围查询一致性:例如
SELECT * WHERE salary BETWEEN 5000 AND 8000 FOR UPDATE会锁住该薪资区间的所有间隙 - 防止死锁链条:通过锁住间隙减少"先删后插"导致的死锁概率
高频面试题深度剖析
面试官问: "为什么UPDATE语句有时会锁住不存在的数据?"
这样答就对了:
"这是因为InnoDB的间隙锁机制在发挥作用。比如执行UPDATE table SET name='A' WHERE id=7,如果表中只有id=5和id=10的记录,MySQL会锁住(5,10)这个间隙。此时其他事务试图插入id=6~9的新数据都会被阻塞,虽然7这条记录本身不存在。"
追问: "如何避免间隙锁导致的并发性能问题?"
加分回答:
"三个实战方案:
1️⃣ 尽量使用等值查询替代范围查询
2️⃣ 在业务允许时使用Read Committed隔离级别
3️⃣ 控制事务粒度,避免长事务持有锁
比如电商扣库存场景,用UPDATE stock SET num=num-1 WHERE id=1001就比WHERE id>1000更安全"

死锁场景实战分析
典型case:
事务A执行:
SELECT * FROM users WHERE age=20 FOR UPDATE; -- 锁住age=20的间隙
INSERT INTO users (age) VALUES (25);
事务B同时执行:
SELECT * FROM users WHERE age=25 FOR UPDATE; -- 锁住age=25的间隙
INSERT INTO users (age) VALUES (20);
这就形成了经典的间隙锁死锁循环。解决方案是统一插入顺序,比如都按age升序处理。
特别福利
准备面试鸭会员?通过面试鸭返利网找我下单,可额外返现25元! 覆盖Java/MySQL/Redis等主流技术栈真题,包含详细题解和避坑指南。

间隙锁的避坑指南
- 索引失效=全表间隙锁:当WHERE条件未命中索引时,MySQL会锁住整个表的所有间隙!
EXPLAIN命令一定要常备 - 唯一索引的妙用:对唯一索引的等值查询(如
WHERE unique_id=100)不会触发间隙锁 - 锁升级机制:当SQL扫描超过20%数据时,InnoDB可能将行锁升级为表锁
- 监控利器:
SHOW ENGINE INNODB STATUS; -- 查看锁等待 SELECT * FROM performance_schema.data_lock_waits; -- 监控锁阻塞
记住:间隙锁是MySQL守护数据一致性的盾牌,用得好能防幻读,用不好就成了性能杀手。面试时结合具体场景分析,展现你对其双面性的理解,绝对能让面试官眼前一亮!


