关注问题解决:快速定位死锁,使用SHOW ENGINE INNODB STATUS查看死锁日志,分析线程冲突的SQL语句,调整事务顺序或加锁策略立即解决问题。
来源1
死锁排查第一步,开启innodb_print_all_deadlocks=1,让MySQL自动记录所有死锁到error log。然后执行show engine innodb statusg打印当前锁等待信息,看到死锁时会有详细的线程信息和锁持有情况。日志里会显示每个事务持有哪些锁,等待哪些锁,直接看SQL就能知道问题了。比如事务A持有表A的行锁等待表B,事务B反过来,就死锁了。
来源2
原理探究:MySQL InnoDB用两阶段锁协议,行锁是基于索引实现的,死锁检测基于wait-for graph。事务并发执行时,如果形成循环等待链,InnoDB检测到后回滚一个事务。日志分析看trx id,trx_mysql_thread_id,锁模式X或S,请求锁类型,就能理解为什么循环了。
来源3
实际解决案例:应用中订单表和库存表,死锁频繁。日志显示select * from order where id=1 for update 和 update stock set num=num-1 where id=1 顺序相反。解决:统一事务先锁订单后锁库存,按主键顺序访问。
来源4
关注解决:用pt-deadlock-logger工具监控死锁,自动解析日志生成报告,找出高频死锁SQL,一键优化索引或拆分事务。比手动看日志快多了。
来源5
深入原理:InnoDB死锁避免用超时机制,innodb_lock_wait_timeout默认50s,超过回滚。但检测是周期性的,不是实时。日志里的---TRANSACTION 12345部分,列出锁队列,WAITING FOR THIS LOCK看到冲突点。
来源6
排查步骤:1. set global innodb_status_output_locks=ON; 2. show engine innodb status; 3. grep Deadlock error.log。分析后,如果是间隙锁导致,加索引或用next-key锁范围缩小。
来源7
FAQ:
Q: 怎么快速开启死锁日志?
A: set global innodb_print_all_deadlocks=1; 记录到mysql-error.log。
Q: 死锁谁回滚?
A: InnoDB回滚undo日志少的那个事务。
Q: 怎么预防死锁?
A: 短事务,按固定顺序加锁,避免大事务。
Q: 死锁日志在哪里看?
A: show engine=innodb status 或 error log。