UPDATE t_order SET status = 'CLOSED' WHERE order_no = ? AND status = 'WAIT_PAY'; INSERT INTO compensate_task(order_no, target, retry) VALUES (?, 'CLOSE_ITEM', 0);
关单接口先更新订单片再更新明细片,第二次更新超时,监控里订单状态是 CLOSED,明细还有 12 条停在 WAIT_PAY,第二天对账才发现。这类现象通常不是突然出现的,往前翻半天日志能看到苗头。
追下去是这么回事:两次更新落在两个物理库上,本地事务只能覆盖第一次,第二次失败后既没回滚也没记录。异常被 catch 后只打了一行日志,调用方拿到的仍是成功。
这次卡住的地方就在「跨片更新补偿」这一环,单独把它拎出来验证,别和其他改动混在同一次发布里。同类问题如果隔一段时间又出现,多半是某个定时任务或重启流程把改动冲掉了。
处理上按这个顺序:把两次更新改成先写本地消息表 再异步推进;明细更新失败时记录待补偿任务 带上订单号和目标状态;补偿任务按状态机幂等执行 重复跑不会改错;对账任务每天比对订单和明细状态。
确认没问题再收工,人为让第二次更新超时 补偿任务跑完后明细全部变成 CLOSED。
