Seata分布式事务失效解决方法

1.问题

博主在学习黑马最新的微服务课程的时候,遇到了一个非常疑惑的问题,Seata分布式事务系统失效,配置无误,@GlobalTransaction注解也已经加入到需要开启事务的方法上,但是分支事务抛出异常并不能使得全局事务进行回滚。

@Override
@GlobalTransactional
public void tryPayOrderByBalance(PayOrderFormDTO payOrderFormDTO) {
        // 1.查询支付单
        PayOrder po = getById(payOrderFormDTO.getId());
        // 2.判断状态
        if(!PayStatus.WAIT_BUYER_PAY.equalsValue(po.getStatus())){
            // 订单不是未支付,状态异常
            throw new BizIllegalException("交易已支付或关闭!");
        }
        // 3.尝试扣减余额
        userClient.deductMoney(payOrderFormDTO.getPw(), po.getAmount());
        // 4.修改支付单状态
        boolean success = markPayOrderSuccess(payOrderFormDTO.getId(), LocalDateTime.now());
        if (!success) {
            throw new BizIllegalException("交易已支付或关闭!");
        }
        // 5.修改订单状态
        orderClient.markOrderPaied(po.getBizOrderNo());
}    

2.排查

博主向ChatGPT进行询问得到了一些答案,但是都没有直击要点,通过一系列的排查,最终发现是分支事务抛出的异常,被以前配置的 FallBack 降级策略给拦截到了,导致 Seata 的 RM 无法监测到,从而无法进行回滚。

1.使用RootContext获取和Seata连接的XID

我们使用 RootContext.getXID() 来判断服务是否能和 Seata 进行正常的连接。

这里使用这个方法,发现每个服务都能获取到 XID。证明连接是没有问题的。

2.undo_log 表有脏数据

当Seata没有正常结束时,每个服务对应数据库中的undo_log表和seata持久化数据库的brach_table、global_table、lock_table、undo_log表都有可能有脏数据没有正确删除,从而导致服务一直回滚,却不成功

解决办法:清除undo_log表以及seata持久化数据库的brach_table、global_table、lock_table、undo_log表中的脏数据

3.Seata 事务处理被 FallBack 回滚函数拦截

这种情况下属于seata服务发现不了下游服务抛出的异常,导致事务不会触发回滚

在这种情况下,我们需要手动控制回滚

手动回滚的方式是使用 GlobalTransactionContext.getCurrent().rollBack(); 方法进行回滚。

boolean success = markPayOrderSuccess(payOrderFormDTO.getId(), LocalDateTime.now());
if (!success) {
    // 手动进行全局事务回滚
    GlobalTransactionContext.getCurrent().rollback();
    throw new BizIllegalException("交易已支付或关闭!");
}

3.总结

这就是关于 Seata 分布式事务失效的解决方法,对于这类问题,需要我们耐心,多方位的思考排查问题,善于使用搜索引擎,获取前人的踩坑点。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

墨白Coding

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值