1. InnoDB 死锁的检测与回滚?
InnoDB 如何检测死锁,检测到后如何回滚?
- 死锁的产生:两个事务互相等待对方持有的锁
- 死锁检测机制:等待图(wait-for graph)检测循环等待
- 回滚策略:牺牲选择回滚代价较小的事务
死锁是多个事务因互相持有对方需要的锁而形成一个循环等待,导致谁都无法继续。InnoDB 通过检测"等待图"(wait-for graph,事务等待关系图)来检测死锁:每当事务等待一个被其他事务持有的锁时,系统检查该等待关系是否形成环,若形成环则发生死锁。检测到死锁后,InnoDB 会选择一个牺牲者(victim)回滚,通常是选择 undo 量最小、回滚代价最小的事务进行回滚,释放其持有的锁,让另一个事务继续执行,并返回错误给被回滚事务(如 ER_LOCK_DEADLOCK)。此外,InnoDB 还有一个锁等待超时机制(innodb_lock_wait_timeout,默认 50 秒)作为兜底:即使未检测到死锁,若一个事务等待锁超过该时间也会被回滚。为避免死锁,应尽量保持一致的加锁顺序、缩短事务时间、合理使用索引缩小锁范围。
死锁是需要"检测 + 回滚"两段机制解决的问题。回答需讲清等待图检测、选择代价最小事务回滚、以及锁等待超时兜底,并简要提及预防策略。
SHOW VARIABLES LIKE 'innodb_lock_wait_timeout'; -- 默认 50 秒
SHOW ENGINE INNODB STATUS\G -- 查看最近死锁信息