mysql-deadlock

MySQL 死锁的定位与处理

现象

应用报 Deadlock found when trying to get lock; try restarting transaction(ERROR 1213)。事务被 InnoDB 选为牺牲者回滚,通常不是数据库坏了,而是加锁顺序或索引问题。

快速定位

SHOW ENGINE INNODB STATUS\G
SHOW VARIABLES LIKE 'innodb_print_all_deadlocks';
SELECT * FROM performance_schema.data_locks;
SELECT * FROM performance_schema.data_waits;

错误日志:

tail -100 /var/log/mysql/error.log | grep -i deadlock

常见根因

  1. 不同事务以相反顺序更新同一批行。
  2. 缺索引导致锁范围扩大,产生间隙锁。
  3. 事务过长,持有锁等待外部调用。
  4. 批量更新顺序不一致或并发过高。
  5. 隔离级别和唯一键冲突导致额外锁。

修复

相关命令

读完自测

合上页面,先回答,再展开对照。

  1. 应用报 ERROR 1213,是否说明数据库本身坏了?
  2. 如何让 MySQL 持续记录死锁信息?
  3. 治理死锁的两个关键方向是什么?
答案
  1. 不是。InnoDB 会选一个事务作为牺牲者回滚。常见原因是加锁顺序不一致或索引问题。
  2. 开启 innodb_print_all_deadlocks。再结合 SHOW ENGINE INNODB STATUS 和错误日志中的 deadlock 记录。
  3. 统一加锁顺序并按固定字段排序更新,同时缩短事务、把外部调用移出事务。补索引也能减少锁范围。