SELECT xid, status FROM tcc_branch WHERE xid = 'TX20260301002';
UPDATE coupon_account SET frozen = frozen - 100
WHERE id = 8812 AND frozen >= 100;

优惠券额度上午被 Cancel 释放,下午 Try 才到,日志里写着「冻结成功」,可全局事务早已结束,这笔额度锁了 48 小时没人释放。先别急着动参数,把报错原文和时间点记下来,顺序反了容易白折腾。

原因不复杂,网络延迟让 Try 在 Cancel 之后才抵达。分支服务只校验了参数,没有校验全局事务的最终状态,一个已经取消的事务又被开出了新分支。

「TCC 悬挂」改完先别急着全量,挑一台机器放半天,真有问题这段时间就能看出来。动手前把原文件复制一份带时间戳,出问题立刻换回去,比现场分析快得多。

一次只改一处,改完立刻验证,几个改动叠在一起,出问题就说不清是谁导致的。

处理上按这个顺序:Try 执行前用事务号查分支表 有 CANCELLED 记录就直接返回失败;协调器下发的请求带上事务状态 终态事务的 Try 一律拒绝;分支表 xid 建唯一索引 挡住重复插入;已冻住的额度按 xid 反查写脚本解冻。

改完只确认一件事:迟到的 Try 返回事务已结束不再冻结 优惠券冻结金额和未结束事务一一对应。

作者 9823189