[seata]@GlobalTransactional同用@Transactional,手动回滚异常

2024-04-28 427 views
5

@GlobalTransactional @Transactional 这两个注解同时使用的时候,使用手动回滚会在抛出异常。 GlobalTransactionContext.reload(RootContext.getXID()).rollback()

org.springframework.transaction.TransactionSystemException: JDBC commit failed; nested exception is java.sql.SQLException: io.seata.core.exception.RmTransactionException: 
Response[ TransactionException[Could not register branch into global session xid = xxx status = Rollbacking while expecting Begin] ]

参考了https://seata.io/zh-cn/blog/seata-spring-boot-aop-aspectj.html 官方案例,和openFeign一起使用,但不论是在 被调用方 手动回滚,还是在发起方手动回滚,入口方法执行完,就会被 TransactionalTemplate中捕捉到。

但是尝试在发起方抛出异常,整个回滚流程是没问题的。去掉 @Transactional 也没问题

Object rs;
try {
    // Do Your Business
    rs = business.execute();
} catch (Throwable ex) {
    // 3. The needed business exception to rollback.
    completeTransactionAfterThrowing(txInfo, tx, ex);   //手动回滚后,总是会回到这里
    throw ex;
}

可以确认的是,被调用的服务在全局事务中,XID也能获取到。也已经看过faq 6和 22,但是没有解决

  • JDK version :openjdk11
  • Seata version: 1.5.2
  • OS :manjaro
  • Others:

回答

3

官网faq

5

官网faq

faq已经看过很多遍了,列出的可能性也能排除 @a364176773 image

8

completeTransactionAfterThrowing(txInfo, tx, ex); //手动回滚后,总是会回到这里 有没有相关为什么会回到这?不是就抛异常抛出来了,如果实在看不明白faq的话,建议用api方式开启和提交/回滚事务,掌握权完全在你手里

4

completeTransactionAfterThrowing(txInfo, tx, ex); //手动回滚后,总是会回到这里 有没有相关为什么会回到这?不是就抛异常抛出来了,如果实在看不明白faq的话,建议用api方式开启和提交/回滚事务,掌握权完全在你手里

@a364176773 是,没错,我也知道抛出异常了,但确实不太明白为什么会有异常,业务都执行完了,数据也正常回滚了,还会对RM进行注册,faq里的出现场景我逐一排查了。

你就当我是个傻子,多说几句,等你有时间,期待回复,感谢。

8

因为你的本地事务走去了commit去注册分支了,你排查问题去看下堆栈的流程先。至于你的本地事务为什么走去commit,那就是要你自己排查了

4

@a364176773 感谢回复。

我应该是犯了一个严重的错误,错误理解了seata全局事务,简单来说,AT模式下,它是本地的数据源代理(DataSourceProxy)做全局锁检查以及记录一些undo的操作,也就是只关心undo的内容,并不侵入本地事务。

我以为增加了@GlobalTransactional之后,它会接管本地事务,所以即使操作了GlobalTransactionContext.reload(RootContext.getXID()).rollback() 也只是最终告诉TC要进行全局回滚,但是本地事务如果不处理(回滚本地事务或者抛出异常),最后还是会commit