源码解析Seata AT模式中分支事务的提交或回滚是如何被触发的

前言

在之前的博客中,已经介绍过了TM在seata AT模式中的处理流程、TC在seata分布式事务中的主要任务以及RM在seata AT模式中的sql语句执行流程,下面我们通过源码讲述分布式事务是如何实现提交或回滚的。

分支事务的提交或回滚

在seata AT模式中,只有当所有的分支事务全部成功提交后,才会触发分布式事务的提交:

public class ConnectionProxy extends AbstractConnectionProxy {
  
    private void processGlobalTransactionCommit() throws SQLException {
        try {
            // 注册分支事务,添加行锁,其实就是分布式锁
            register();
        } catch (TransactionException e) {
            recognizeLockKeyConflictException(e, context.buildLockKeys());
        }
        try {
          // 插入undolog
            UndoLogManagerFactory.getUndoLogManager(this.getDbType()).flushUndoLogs(this);
            // 提交本地事务
            targetConnection.commit();
        } catch (Throwable ex) {
            LOGGER.error("process connectionProxy commit error: {}", ex.getMessage(), ex);
            // 上报分支事务提交失败状态
            report(false);
            // 抛出异常,最终会被TM捕捉到,触发分布式事务的回滚
            throw new SQLException(ex);
        }
        if (IS_REPORT_SUCCESS_ENABLE) {
            // 上报分支事务成功提交状态
            report(true);
        }
        // 恢复现场
        context.reset();
    }
}

在上述源码分析中,当所有的RM分支事务提交成功后,TC会接收到所有RM分支事务的状态,代码最终会执行到TM的模版逻辑中。

TM触发分布式事务的提交或回滚

TM模版代码:

public Object execute(TransactionalExecutor business) throws Throwable {
            // 1. 拿到整理好的@GlobalTransactional注解里面的配置信息
            TransactionInfo txInfo = business.getTransactionInfo();
            if (txInfo == null) {
                throw new ShouldNeverHappenException("transactionInfo does not exist");
            }
            // 1.1 获取当前的分布式事务,如果为null的话,说明这是分布式事务的发起者;如果不为null,说明这是分布式事务的参与者
            GlobalTransaction tx = GlobalTransactionContext.getCurrent();
    
            // 1.2 获取分布式事务的传播级别,其实就是按照spring的传播级别来一套,区别就是spring事务是本地事务,这是分布式事务,原理都一样
            Propagation propagation = txInfo.getPropagation();
            SuspendedResourcesHolder suspendedResourcesHolder = null;
            try {
                // 这个switch里面全都是处理分布式事务传播级别的
                switch (propagation) {
                    // 如果不支持分布式事务,如果当前存在事务,那么先挂起当前的分布式事务,再执行业务逻辑
                    case NOT_SUPPORTED:
                        // 分布式事务存在,先挂起
                        if (existingTransaction(tx)) {
                            suspendedResourcesHolder = tx.suspend();
                        }
                        // 执行业务逻辑
                        return business.execute();
                    // 如果是每次都要创建一个新的分布式事务,先把当前存在的分布式事务挂起,然后创建一个新分布式事务
                    case REQUIRES_NEW:
                        // 如果分布式事务存在,先挂起当前分布式事务,再创建一个新的分布式事务
                        if (existingTransaction(tx)) {
                            suspendedResourcesHolder = tx.suspend();
                            tx = GlobalTransactionContext.createNew();
                        }
                        // 之所以用break,是为了后面的代码和其他的传播级别一起共用,业务逻辑肯定还是要执行的
                        break;
                    // 如果支持分布式事务,如果当前不存在分布式事务,那么直接执行业务逻辑,否则以分布式事务的方式执行业务逻辑
                    case SUPPORTS:
                        // 如果不存在分布式事务,直接执行业务逻辑
                        if (notExistingTransaction(tx)) {
                            return business.execute();
                        }
                        // 否则,以分布式事务的方式执行业务逻辑
                        break;
                    // 如果有分布式事务,就在当前分布式事务下执行业务逻辑,否则创建一个新的分布式事务执行业务逻辑
                    case REQUIRED:
                        // If current transaction is existing, execute with current transaction,
                        // else continue and execute with new transaction.
                        break;
                    // 如果不允许有分布式事务,那么一旦发现存在分布式事务,直接抛异常;只有不存在分布式事务的时候才正常执行
                    case NEVER:
                        // 存在分布式事务,抛异常
                        if (existingTransaction(tx)) {
                            throw new TransactionException(
                                String.format("Existing transaction found for transaction marked with propagation 'never', xid = %s"
                                        , tx.getXid()));
                        } else {
                            // 不存在分布式事务,执行业务逻辑
              
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值