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

异常崩溃情况下,有些未完成的事务会一直处于Trying阶段无法继续下去,造成事务不一致 #8

Closed
kixiong opened this issue May 17, 2016 · 7 comments

Comments

@kixiong
Copy link

kixiong commented May 17, 2016

分析代码发现TransactionManager代码中的commit和rollback方法中,如果在更新数据库记录变更事务状态前,虚拟机被kill了,之前Trying阶段的事务会一直处于Trying阶段,无法继续处理下去,TransactionRecoveryJob不处理这中情况,造成事务不一致。是否可以考虑加上事务超时机制,后台定时扫描超时Trying阶段事务,使得这中情况下可以保证事务一致性。

public void rollback() {

        Transaction transaction = getCurrentTransaction();

        transaction.changeStatus(TransactionStatus.CANCELLING);

        /**********************************************************************************/
        /**在这个位置JVM崩溃了,事务将会一直处于Trying阶段***/
        /**********************************************************************************/

        try {
            transactionConfigurator.getTransactionRepository().update(transaction);
            transaction.rollback();
            transactionConfigurator.getTransactionRepository().delete(transaction);
        } catch (Throwable rollbackException) {
            if (transaction.getTransactionType().equals(TransactionType.ROOT)) {
                transactionConfigurator.getTransactionRepository().addErrorTransaction(transaction);
            }
            throw new RuntimeException(rollbackException);
        }

    }
@changmingxie
Copy link
Owner

changmingxie commented May 19, 2016

@kixiong
如果commit或rollback过程中kill jvm了,当然TransactionRecoveryJob也无法继续恢复了。当重启动应用后TransactionRecoveryJob会自动恢复这些未终结的事务(最大尝试恢复次数不多于N次,如果N次后依旧没有恢复,则需要人工干预)

@kixiong
Copy link
Author

kixiong commented May 24, 2016

@changmingxie
非常感谢您的热情回答。

  1. 一般情况下,dubbo部署都是集群部署,节点崩溃了是大概率事件,在集群情况下可能不会去重启这个节点,而其他节点在这个TCC框架中又没有机制去扫描到库表中有这种需要回滚的事务,所以在实际集群部署情况下,如果不重启节点或新增加节点,这个事务会一直存在的。
  2. 在集群情况下,在重启节点后,存在误将其他节点正在处理中的Trying事务给Rollback掉,原因如下:
    在代码中:
 StringBuilder builder = new StringBuilder();
            builder.append("SELECT GLOBAL_TX_ID, BRANCH_QUALIFIER, CONTENT,STATUS,TRANSACTION_TYPE,RETRIED_COUNT" +
                    "  FROM TCC_TRANSACTION ");

重启后,这个重启的节点将会加载所有的事务,包括其他节点正在处理中的事务,而这些事务中有可能是其他节点刚刚创建或正处于Trying节点正在处理中的事务,都将会被这个重启节点的事务恢复器给Rollback掉,造成系统异常。

@changmingxie
Copy link
Owner

@kixiong
感谢你指出不足。
第一点 如果节点挂了 又没有重启,那么这个节点中还未完成的事务会一直存在,目前没有特别处理,需要干预。
第二点 重启新的节点,是会存在你说的问题,这是系统的一个设计漏洞,可以考虑 在节点重启时 只恢复超时的事务(定义一个事务最大超时限制)并做防重复恢复(如果多个节点同时启动)。

@weldon01
Copy link

@changmingxie 请问针对@kixiong 提的两个问题,在新的V1.1.0版中是否做了改进和修复?

@changmingxie
Copy link
Owner

@weldon01
是的。如果发现有什么问题,欢迎提出!

@654894017
Copy link

@changmingxie 如果节点挂了 又没有重启,那么这个节点中还未完成的事务会一直存在,目前没有特别处理,需要干预。 1.1.0版本是这么解决问题的

@xuyang0902
Copy link

其实在更新事务单据状态的时候当前节点挂掉 这种情况我直接走cancel 这类业务 应该也能接受吧。

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

5 participants