数据库锁与死锁。
未标记
考查重点:锁冲突与循环等待。锁让冲突操作等待;事务按相反顺序拿锁可形成等待环,统一加锁顺序、缩短事务并对死锁回滚重试
本题目录
参考答案
本答案基于相关资料,由 AI 辅助编写,供学习与面试准备参考。如有疏漏,欢迎反馈指正。
核心回答
数据库锁用于协调并发访问,避免不兼容的操作同时破坏数据约束。以MySQL InnoDB为例,既有记录和范围相关的锁,也有表级意向锁、元数据锁等;锁的实际范围受语句、索引和隔离级别影响。
死锁是多个事务互相等待对方持有的锁,形成等待环。例如事务A先锁账户1、再等账户2,事务B先锁账户2、再等账户1,双方都不能继续。它不同于单纯等待一个最终会结束的长事务。
先区分几类机制
记录锁保护索引记录;间隙锁保护索引记录之间的间隙,主要限制插入;Next-Key Lock结合记录和前方间隙。不是每次查询都加这三类锁,唯一键等值查询、范围查询以及RC/RR隔离级别的行为不同。
共享锁与排他锁表达兼容关系:排他锁会阻止其他不兼容加锁,但普通MVCC快照读通常无需因这把记录锁等待。锁定读则读取当前可用数据并获取相应锁,事务提交或回滚后释放相关事务锁。
意向锁表明事务准备在表内获取某类行锁,便于协调表锁;元数据锁保护表结构访问,DDL等待也可能来自长事务,不能把所有“数据库卡住”都当行锁死锁。
死锁怎样处理
统一多资源加锁顺序,缩短事务,减少扫描和持锁范围,不在事务中等待外部服务。InnoDB通常会检测死锁并回滚一个受害者,应用仍需识别错误、清理当前事务,必要时在幂等基础上有限重试。
排查时查看死锁记录、持锁与等待语句、事务持续时间及实际索引扫描范围。单纯增大锁等待超时不能消除等待环;降低隔离级别也不能保证不再死锁。
追问
应用使用版本号乐观更新,数据库底层执行更新仍可能用锁。乐观策略解决的是并发冲突的检测方式,并不意味着多语句事务绝无死锁。
参考资料
- 国内:JavaGuide / Snailclimb:接口幂等性设计详解:借鉴版本号条件更新与锁定读的对比,解释正文中乐观并发控制和悲观锁如何落实到业务更新。
- 国内:JavaGuide / Snailclimb:MySQL 事务隔离级别详解:快照读和当前读的区别说明普通查询为何不能代替需要保护后续修改的锁定读。
- 国内:小林 coding:MySQL 有哪些锁?:参考行锁与事务的说明,解释正文中锁范围的判断依据及缩短持锁时间的原因。
- 国外:MySQL / Oracle:Locking Reads:锁定读与计数器示例说明悲观并发控制如何保护先读后改,以及事务结束时如何释放锁。
- 国外:MySQL / Oracle:Deadlocks in InnoDB:依据加锁顺序与死锁受害者回滚的说明,补充正文中统一加锁顺序、回滚与有限重试的处理。


