mysql|线上频出MySQL死锁问题!分享一下教科书般的排查和分析过程( 五 )


本文插图

可以知道 , 其实死锁日志的 SQL 是模糊的 , 但是原因是正确的 , 至于具体是哪些 SQL 导致的死锁 , 是需要从业务日志来判定 。
6. 善后
模拟出了事务2的场景 , 我们就可以对回滚的 SQL 执行 , 来人工修复受到影响的用户数据(客户第一) 。 也可以知道其实 transactionMoney() 方法不应该加事务 , 因为该业务场景每个用户的更新是独立的不应该互相受到影响 , 但是当某条更新失败时 , 我们也要打印对应的日志 。
这里我们就知道为什么之前大半年都没问题 , 最近才频发这种异常 , 因为只有当两个事务同时执行 , 并且两个事务中包含了相同的两个或两个以上的 user_id 才会可能触发该异常 。 而这种 user_id 都是所谓的大用户 , 像该示例中的 user_id 为 1、2 是小用户 , 虽然它们也受到了影响 , 但是频率是没有 user_id 为 4、5 这种大用户高的 。
在实际的业务场景也证实了这点 , 不仅是发生故障的时间是集中在高峰期 , 而且发生故障的用户也经常有那几个熟面孔 , 经过后面复盘 , 这几个熟面孔用户也就是我们所说的”大用户“(业务操作频率高的用户) 。
7. 模拟项目源码
为了模拟真实场景中的方法调用(消息接收调用执行) , 使用了线程来模拟 。 并且使用线程睡眠来保证每个事务执行够长 , 来让每次模拟执行都出现异常 。
mysql|线上频出MySQL死锁问题!分享一下教科书般的排查和分析过程
本文插图

项目结构比较简单 ,Controller -&gt Manager -&gt Service -&gt Mapper -&gt DB , 执行 curl "localhost:8080/test/consumer" 后 , 查看命令行输出即可看到业务异常日志 。
对应的死锁日志需要到对应的数据库执行:show engine innodb status 后可看到 。
8. 最后
中间查阅了很多资料 , 发现有个项目总结了所有的死锁日志对应的可能 SQL:https://github.com/aneasystone/mysql-deadlocks , 里面也讲解了加锁的各个细节过程 , 是非常值得一看的 。 以下为该项目的部分截图:
mysql|线上频出MySQL死锁问题!分享一下教科书般的排查和分析过程
本文插图

当遇到复杂的业务场景 , 尤其是不熟悉的时候 , 这个是一个很好的参考资料 。
业务日志记录、全链路跟踪是非常非常重要的声明:转载此文是出于传递更多信息之目的 。 若有来源标注错误或侵犯了您的合法权益 , 请作者持权属证明与本网联系 , 我们将及时更正、删除 , 谢谢 。邮箱地址:newmedia@xxcb.cn


推荐阅读