Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

是否支持防悬挂控制 #328

Open
changmingxie opened this issue Jun 3, 2021 · 4 comments
Open

是否支持防悬挂控制 #328

changmingxie opened this issue Jun 3, 2021 · 4 comments

Comments

@changmingxie
Copy link
Owner

changmingxie commented Jun 3, 2021

悬挂的意思是:在分支事务执行情况下,Cancel 比 Try 接口先执行,出现的原因是 Try 由于网络拥堵而超时,事务管理器生成回滚,触发 Cancel 接口,而最终又收到了 Try 接口调用,但是 Cancel 比 Try 先到。

框架是允许空回滚的逻辑,如果分支事务没有(有可能try还没有开始执行,或者事务已经回滚过,事务删除了)回滚会返回成功,事务管理器认为事务已回滚成功,整个事务回滚结束。而如果try方法最终到达,开始执行,分支事务创建,由于主事务已经回滚结束了,该分支事务不会因主事务回滚而被触发回滚了。这种情况下,定时恢复任务回扫描该分支事务,检查其主事务的状态,发现没有主事务,则回滚该分支事务。

@Rocky-Hu
Copy link

Rocky-Hu commented Mar 13, 2022

定时恢复任务回扫描该分支事务,检查其主事务的状态,发现没有主事务,则回滚该分支事务

主事务所在的服务为A, 分支事务所在的服务为B,服务B的定时任务扫描分支事务日志,发现TRY_SUCCESS或TRY_FAILED的记录,然后查询主事务的事务日志。服务B和服务A用得如果不是一个数据库,服务B怎么查主事务?还有就是服务A发起回滚成功后,事务日志是删除了的,假设就是两个服务用得是一个数据库一张表,因为主事务的日志已经删除了,也是查不到的。防悬挂的问题还有吧。

隔了好久再次回复,不知道理解对不。

@haidi-kong
Copy link

` //check the root transaction
Transaction rootTransaction = transactionRepository.findByRootXid(transaction.getRootXid());

                    if (rootTransaction == null) {
                        // In this case means the root transaction is already rollback.
                        // Need cancel this branch transaction.
                        rollbackTransaction(transactionRepository, transaction);
                    } else {
                        switch (rootTransaction.getStatus()) {
                            case CONFIRMING:
                                commitTransaction(transactionRepository, transaction);
                                break;
                            case CANCELLING:
                                rollbackTransaction(transactionRepository, transaction);
                                break;
                            default:
                                break;
                        }
                    }`

看来下源码的地方,整个分布式事务异常的情况下去cancel是没有问题的,业务上做无损控制就行。但是如果在事务都是成功的情况,这时候定时任务启动,去做在未提交事务的recovery,由于主事务无法获取(不在同一个库),岂不是会将要commit的事务回滚掉?

不知道会存在这个问题吗?

@changmingxie
Copy link
Owner Author

还有就是服务A发起回滚成

  1. 服务B和服务A用得如果不是一个数据库, 服务B不能查主事务,只有能服务A恢复后通过A的主事务来驱动恢复。
  2. AB两个服务用得是一个数据库一张表,因为主事务的日志已经删除了,B是查不到的,会认为主事务已经会滚了,B的分支事务执行会滚。

@changmingxie
Copy link
Owner Author

在同一个
但是如果在事务都是成功的情况,这时候定时任务启动,去做在未提交事务的recovery,由于主事务无法获取(不在同一个库),会去判断 分支是事务的状态,如果是CONFIRMING,就会去 confirm分支事务,如果还是TRYING,则不处理,等待主事务来驱动恢复。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants