SpringCloud+Seata+MybatisPlus多数据源@GlobalTransactional异常数据未回滚事务失效的解决方案

SpringCloud整合Seata1.6.1部署与使用Nacos方式

一、问题解析

造成分布式事务失效,数据回滚异常的情况会有很多,下面介绍两种我遇到的情况,与对应的解决方案。

1.1 全局异常捕获吞异常导致分布式事务失效

一般的微服务都会使用@RestControllerAdvice全局异常捕获对接口出现的异常进行捕获,包装成统一的数据结构响应给前端。
如果A服务通过远程调用B服务A服务作为全局事务的入口,当B服务内部出现异常,被B服务的全局异常捕获到返回,A服务得到的响应结果并不是一个Exception,可能是一个经过B服务包装的JSON对象{"code": 500,"msg":"method error"}
此时A服务会认为B服务异常已经被处理,异常没有被A服务的全局事务感知到,所以导致全局事务未能回滚

1.2 MybatisPlus多数据源dynamic-datasource-spring-boot-starter导致事务失效

当服务中使用了MybatisPlus多数据源dynamic-datasource-spring-boot-starter,如果没有正确的配置,可能也会出现事务失效的问题。

二、解决方案

2.1 全局异常事务失效解决

官方的常见问题解决文档中关于AT模式使用注意事项:常见问题
Q: 20. 使用 AT 模式需要的注意事项有哪些 ?
A:

  1. 必须使用代理数据源,有 3 种形式可以代理数据源:
  • 依赖 seata-spring-boot-starter 时,自动代理数据源,无需额外处理。
  • 依赖 seata-all 时,使用 @EnableAutoDataSourceProxy (since 1.1.0) 注解,注解参数可选择 jdk 代理或者 cglib 代理。
  • 依赖 seata-all 时,也可以手动使用 DatasourceProxy 来包装 DataSource。
  1. 配置 GlobalTransactionScanner,使用 seata-all 时需要手动配置,使用 seata-spring-boot-starter 时无需额外处理。
  2. 业务表中必须包含单列主键,若存在复合主键,请参考问题 13 。
  3. 每个业务库中必须包含 undo_log 表,若与分库分表组件联用,分库不分表。
  4. 跨微服务链路的事务需要对相应 RPC 框架支持,目前 seata-all 中已经支持:Apache Dubbo、Alibaba Dubbo、sofa-RPC、Motan、gRpc、httpClient,对于 Spring Cloud 的支持,请大家引用 spring-cloud-alibaba-seata。其他自研框架、异步模型、消息消费事务模型请结合 API 自行支持。
  5. 目前AT模式支持的数据库有:MySQL、Oracle、PostgreSQL和 TiDB。
  6. 使用注解开启分布式事务时,若默认服务 provider 端加入 consumer 端的事务,provider 可不标注注解。但是,provider 同样需要相应的依赖和配置,仅可省略注解。
  7. 使用注解开启分布式事务时,若要求事务回滚,必须将异常抛出到事务的发起方,被事务发起方的 @GlobalTransactional 注解感知到。provide 直接抛出异常 或 定义错误码由 consumer 判断再抛出异常。

方案一:官方的解决:
通过AOP动态创建/关闭Seata分布式事务

方案二:
A服务FeignClient的service上增加AOP切面,A服务远程调用B服务,B服务内部异常,在@AfterReturning切点中判断B服务接口的响应内容,判断响应码为特定值时,可以直接抛出异常,让全局事务感知,也可以调用seata回滚API进行事务回滚GlobalTransactionContext.reload(RootContext.getXID()).rollback();

2.2 多数据源导致全局事务失效解决

使用多数据源的情况下每个数据源都需要用seata进行代理,

  • spring.datasource.dynamic.seata: true 可以解决全局事务失效问题。
  • seata.enable-auto-data-source-proxy: false 可以解决事务执行完毕,undo_log表中日志未清除的问题。
  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

banmajio

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

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

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

打赏作者

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

抵扣说明:

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

余额充值