《100个“反常识”经验12:死锁日志怎么看?》
本期摘要数据库突然卡死应用日志里一堆“Deadlock found”。你遇到过吗死锁不是Bug是并发事务资源竞争的正常现象。本文不讲复杂的死锁理论直接带你读MySQL死锁日志怎么看事务1在等什么锁、事务2拿着什么锁、谁被回滚了。看完你就能在三分钟内定位到问题SQL而不是盲目重启。一次让人想砸键盘的故障业务高峰期突然大量接口超时。应用日志里全是textDeadlock found when trying to get lock; try restarting transaction登录MySQL执行sqlSHOW ENGINE INNODB STATUS\G找到 LATEST DETECTED DEADLOCK 这一段。看到日志的瞬间两眼一黑——全是十六进制地址和晦涩的锁信息根本不知道在说什么。死锁日志到底在说什么一条典型的死锁日志长这样sql*** (1) TRANSACTION: TRANSACTION 310479085, ACTIVE 12 sec starting index read mysql tables in use 1, locked 1 LOCK WAIT 2 lock struct(s), heap size 1136, 1 row lock(s) *** (1) WAITING FOR THIS LOCK TO BE GRANTED: RECORD LOCKS space id 104 page no 45 n bits 80 index idx_user_id of table db.orders trx id 310479085 lock_mode X locks rec but not gap waiting *** (2) TRANSACTION: TRANSACTION 310479086, ACTIVE 10 sec starting index read mysql tables in use 1, locked 1 4 lock struct(s), heap size 1136, 3 row lock(s) *** (2) HOLDS THE LOCK(S): RECORD LOCKS space id 104 page no 45 n bits 80 index idx_user_id of table db.orders trx id 310479086 lock_mode X locks rec but not gap *** (2) WAITING FOR THIS LOCK TO BE GRANTED: RECORD LOCKS space id 104 page no 52 n bits 80 index idx_status of table db.orders trx id 310479086 lock_mode X locks rec but not gap waiting *** (2) ROLLBACK TO SAVE POINT拆开来看每个字段都有含义字段含义对我们有用的信息TRANSACTION 310479085事务ID区分两个事务ACTIVE 12 sec事务活跃时间超过几秒就要警惕waiting for this lock在等哪个锁告诉你被卡在哪个索引上holds the lock(s)持有哪些锁告诉你对方占了什么index idx_user_id索引名称定位到具体表和索引tabledb.orders表名哪个表出问题了ROLLBACK谁被回滚了事务2被干掉事务1继续两分钟定位问题的思路第一步找到事务1等什么看 (1) WAITING FOR THIS LOCK它被卡在idx_user_id上在等一个行锁。第二步找到事务2占什么看 (2) HOLDS THE LOCK(S)它占着idx_user_id上的锁同时在等idx_status上的锁。第三步得出结论事务1需要 user_idxxx 的锁事务2占着它不放同时事务2又在等另一条记录的锁。循环等待。第四步回看业务代码两个事务的SQL分别是事务1sqlUPDATE orders SET status paid WHERE user_id 123 AND order_id 456;事务2sqlUPDATE orders SET status shipped WHERE status paid AND order_id 456;事务1先锁住了 user_id 索引事务2锁住了 order_id 索引互相等待。如何解决临时方案kill掉被回滚的事务对应的应用连接释放锁。永久方案统一事务内的SQL顺序让所有事务按相同顺序访问表和索引优化索引减少行锁范围拆分大事务缩短锁持有时间使用 READ COMMITTED 隔离级别减少间隙锁快速排查脚本sql-- 查看当前锁等待 SELECT * FROM information_schema.innodb_lock_waits; -- 查看当前事务 SELECT * FROM information_schema.innodb_trx WHERE trx_state LOCK WAIT;下期预告《100个“反常识”经验13凌晨3点我误把生产当测试》
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2561100.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!