支付成功和风控通过两个Webhook几乎同时到达,偶尔一个请求报 Deadlock found when trying to get lock。重放又成功,所以很容易被当成数据库抖动。其实两个事务锁表顺序相反:A先锁sales_order再锁自定义表,B反过来。
SHOW ENGINE INNODB STATUS\G # 同时保留Magento exception.log中的请求ID和事件ID
从LATEST DETECTED DEADLOCK里看双方持有和等待的索引,不要只看SQL文本。统一业务更新的锁顺序,事务里移除外部HTTP调用和大查询。
重试可以有,但必须幂等
对MySQL死锁做有限次数、带随机退避的重试是合理的;Webhook事件ID要有唯一键,避免第一次事务其实部分完成、重试又创建一张Invoice。
压测用两个并发事件反复打同一测试订单,确认无重复交易、无重复邮件,死锁重试次数也在监控里可见。简单把innodb_lock_wait_timeout调大不会解决死锁。

