JJava 知识库
JAVA INTERVIEW

高频面试题

MySQL高级约 2 分钟

支付回调和退款任务并发更新订单时频繁死锁,你会怎么查死锁日志并改造代码?

参考回答约 2 分钟 · 口语表达
我的判断

支付回调与退款死锁,先从 InnoDB 死锁日志还原双方持锁与等待顺序,再统一访问顺序、缩短事务并加有限重试。

我会保存 SHOW ENGINE INNODB STATUS 的 latest deadlock 或开启死锁日志,拿到两边 SQL、事务持有的锁、等待的索引记录和被回滚的一方。再把 SQL 映射回支付回调与退款代码,确认是否一个先更订单再更支付单,另一个顺序相反。

修复通常是所有路径按同一顺序访问资源,例如都先锁订单、再锁支付记录;查询条件补正确索引,避免锁住比预期更多的行或 gap;远程调用、消息发送移出数据库事务。

应用层会捕获死锁错误做 有限次数、带抖动的整体事务重试,因为被回滚事务之前的所有 SQL 都已失效。业务请求号和状态条件保证重试幂等。

上线后观察死锁次数、事务时长、锁等待和受影响订单,并并发回放“回调 + 退款”相反时序。只把隔离级别调低,未必能解决记录锁顺序问题。

思路拆解问题分析

死锁不是“数据库偶尔抽风”,而是多个事务形成等待环。数据库主动回滚一方是保护机制;真正要修的是 资源访问顺序、锁范围和事务长度