Seata: 分支事务回滚了,但是TM还是正常的提交

Created on 8 Apr 2020  ·  12Comments  ·  Source: seata/seata

  • [ ] I have searched the issues of this repository and believe that this is not a duplicate.

Ⅰ. Issue Description

分支 try{} catch(){} 了异常,返回正常。 可是 TM 提交了commit
代码
ConnectionProxy

@Override
public void rollback() throws SQLException {
targetConnection.rollback();
if (context.inGlobalTransaction()) {
if (context.isBranchRegistered()) {
report(false);
}
}
context.reset();
}

并没有走到 report(false);
这块是不是可以优化一下

Most helpful comment

二阶段回滚是同步。
tc根据各个rm report结果决议二阶段行为我觉得可能需要,我跟小伙伴们讨论下。

All 12 comments

image
不是很明白您描述的意思 您是说 分支中异常被自行try catch后 应该走回滚路线么 不应该自行try catch 异常之后视为正常 而是应该视为异常 回滚整个全剧事物 如果是这样 那seata怎么知道异常被自行捕获了?

image
不是很明白您描述的意思 您是说 分支中异常被自行try catch后 应该走回滚路线么 不应该自行try catch 异常之后视为正常 而是应该视为异常 回滚整个全剧事物 如果是这样 那seata怎么知道异常被自行捕获了?

是这个意思。 因为代码执行到 rollback里了,可是没进入 report(false) 。
这样consumer端就要判断rpc的返回状态了(比如status=0业务正常,=-1 业务异常)。
server端代码还没看,我再了解下 report(false)有什么作用吧。

你这个和另外一个issue解决方式好像类似 可否先记录提交还是回滚的状态 在第二阶段tc通知的时候进行处理

你这个和另外一个issue解决方式好像类似 可否先记录提交还是回滚的状态 在第二阶段tc通知的时候进行处理

@Garlichead 两码事
1.这个rollback只有test case调用,业务执行时不可能进来
2.这个issue就是普通的把异常吃掉了,没通知到TM,了解下seata原理
3.这个issue可以用参与人回滚 https://github.com/seata/seata/pull/2101,不过参与人吃掉了异常,虽然最终数据没影响,但是tm会拿不到业务异常,只会抛出找不到全局事务的异常,不推荐吃掉异常

你这个和另外一个issue解决方式好像类似 可否先记录提交还是回滚的状态 在第二阶段tc通知的时候进行处理

@Garlichead 两码事

1.这个rollback只有test case调用,业务执行时不可能进来

2.这个issue就是普通的把异常吃掉了,没通知到TM,了解下seata原理

3.这个issue可以用参与人回滚 https://github.com/seata/seata/pull/2101,不过参与人吃掉了异常,虽然最终数据没影响,但是tm会拿不到业务异常,只会抛出找不到全局事务的异常,不推荐吃掉异常

1 rollback是seata层在第二阶段(完成阶段)发起决议完成后已经确定全局回滚才会执行rollback 这一点 我理解 业务层是不可能进来的 我想题主的想法想通过业务层去驱动rollback 只能是返回一个异常状态给seata 这样tm在发起决议的时候才知道需要全局回滚 是否可以自行try catch之后 执行完业务逻辑之后 throw一个异常 这样tm发起决议后 因为有分之抛出异常 就可以决议为全局回滚
2 您说的业务自行try catch了异常后 后续执行机制 个人查阅官方文档 应该是业务上报状态给tc 个人猜想tc会把状态存储在context中 以至于tm发起决议的时候可以知道各个分支事务的状态
3 您说的参与人吃掉了异常 数据没有影响 但是tm捕获不到业务异常 也就是可以理解tm是可以捕获到异常 但是异常被业务trycatch了 所以无法捕获业务异常 但是可以知道业务执行块里面发生了异常 这一点我不懂 因为异常在内部被捕获处理了 并没有throw tm如何知道内部发生了异常呢? 假如tm知道发生了分之异常 则要进行全局异常回滚 如果上游分之进行了本地事务提交 则需要进行回滚 也不会有其他分支脏数据 只是tm会认为这个异常默认是全局异常抛出 不利于异常抛出友好度 那反过来思考 分之代码块catch了exception 后 return true 是不是可以理解分之上报了执行正常给tc 这样tm发起决议的时候假设其他分支都是正常 那是不是认定为全局提交 而业务所需要的是全局回滚 这样就会导致其他分支的脏数据了

3.使用参与人回滚功能会提前让tc执行全局回滚,等到tm执行或者上报时跟tc通信会找不到这个全局事务或者状态不对,因此抛出异常.
目前决议是由tm决定并上报tc,参与方report并不影响结果,你们是希望由tc根据各个report来决议?

3.使用参与人回滚功能会提前让tc执行全局回滚,等到tm执行或者上报时跟tc通信会找不到这个全局事务或者状态不对,因此抛出异常.

目前决议是由tm决定并上报tc,参与方report并不影响结果,你们是希望由tc根据各个report来决议?

明白 参与人回滚功能我得去分析下 那这样参与人功能就满足题主的需求了 不是希望tc根据各个report进行决议 我查阅官方文档是分之report状态给tc tm发起决议 这里tm要根据xid和branchid去tc获取各个分之状态吧? 而参与人回滚功能tc已经执行了全局回滚了 所以xid就从context中销毁了 就找不到了出现xid cannot found exception 理解正常机制下全局提交和回滚是tm决议全局提交或回滚通知tc 然后tc再异步通知rm进行全局提交或回滚 那这里参与人回滚功能就不要经过tm 直接让tc异步通知所有rm执行全局回滚了

二阶段回滚是同步。
tc根据各个rm report结果决议二阶段行为我觉得可能需要,我跟小伙伴们讨论下。

有解决方案了吗?我现在也遇到了这个问题。如果我在controller层捕获了异常,我的这个分支事务会回滚,但是如果tm还是发起提交的话,其他子事务还是能提交掉。能不能在子分支事务抛出异常时,不管controller有没有捕获,都能够记录此子事务失败,全局需要回滚呢。

刚测试了一下,甚至controller抛出了异常,如果tm还是正常提交的话,最终还是会导致不一致。是我哪里有问题吗?不太理解

也就是说rm即使抛了异常,tc看起来就像毫不知情一样。tm发起提交就提交了

总体感觉就是tm想全局提交就全局提交,想全局回滚就全局回滚。其实并不会在意某个分支事务的成功与否。这是否会有问题呢?我还在思考。

Was this page helpful?
0 / 5 - 0 ratings