下单事务里先调了 mqTemplate.send,后面库存不足抛异常,事务回滚,订单表没有记录。消费者却收到「订单创建成功」,回头查订单查不到。碰到这种情况,我一般先确认改动有没有真的生效。

原因不复杂,消息发送走网络调用,不受本地事务控制,发出去了就收不回。事务回滚只影响数据库,消费端拿到一条指向不存在订单的消息。

碰到「事务内发消息」这类问题,我习惯先把当前配置原样备份一份,改坏了立刻换回来,不用现场推。报错里带路径的,先去看那个路径在不在、权限对不对。

TransactionSynchronizationManager.registerSynchronization(
  new TransactionSynchronizationAdapter() {
    public void afterCommit() { mqTemplate.send(msg); }
  });

同一份配置存在多处的,先确认改的是被加载的那一份。

具体做法是,发送动作挪到事务提交之后 用 afterCommit 回调;必须和事务绑定的场景改用本地消息表;消费端按业务单号查不到数据先重试再丢弃;已投出的脏消息记录单号人工核对。

最后用这个标准收尾,事务回滚的用例里 MQ 没有消息 提交的用例里消息出现在提交之后。

作者 9823189