seata AT模式源码(二)

880 阅读8分钟

开启了分布式事务后,下一步就需要执行目标方法了。

1、执行目标方法

1.1 seata代理数据源

seata要实现分布式事务,前提之一就是我们要把数据源交给seata进行管理

在上篇seata AT模式源码(一)中,提到的seata整合springboot部分,seata向容器中注入了SeataAutoDataSourceProxyCreator,完成了对数据源的代理。

SeataAutoDataSourceProxyCreator是一个BeanPostProcessor类型的bean,继承了AbstractAutoProxyCreator类,重写了shouldSkip方法(表示哪些对象要进行代理)和getAdvicesAndAdvisorsForBean方法(表示代理逻辑,即要添加到拦截器链里的拦截器)

public class SeataAutoDataSourceProxyCreator extends AbstractAutoProxyCreator {
    private static final Logger LOGGER = LoggerFactory.getLogger(SeataAutoDataSourceProxyCreator.class);
    private final String[] excludes;
    /**
     * 代表代理逻辑的拦截器
     */
    private final Advisor advisor = new DefaultIntroductionAdvisor(new SeataAutoDataSourceProxyAdvice());

    public SeataAutoDataSourceProxyCreator(boolean useJdkProxy, String[] excludes) {
        this.excludes = excludes;
        setProxyTargetClass(!useJdkProxy);
    }
    
    //需要添加到拦截器链里的拦截器
    @Override
    protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource customTargetSource) throws BeansException {
        if (LOGGER.isInfoEnabled()) {
            LOGGER.info("Auto proxy of [{}]", beanName);
        }
        return new Object[]{advisor};
    }


    /**
     * 哪些bean需要跳过(不进行代理)
     * @param beanClass
     * @param beanName
     * @return
     */
    @Override
    protected boolean shouldSkip(Class<?> beanClass, String beanName) {
        //DataSource类型的bean不跳过(即需要代理)
        return SeataProxy.class.isAssignableFrom(beanClass) ||
            !DataSource.class.isAssignableFrom(beanClass) ||
            Arrays.asList(excludes).contains(beanClass.getName());
    }
}

可以看到,SeataAutoDataSourceProxyCreator代理DataSource类型的bean,代理逻辑是SeataAutoDataSourceProxyCreator这个拦截器。

public class SeataAutoDataSourceProxyAdvice implements MethodInterceptor, IntroductionInfo {

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        
        /**
         * 将dataSource和DataSourceProxy的映射关系放到map中
         * 即一个DataSourceProxy对应一个DataSource
         * DataSourceProxy创建时,会初始化一个定时任务,定数刷新数据表的元数据信息(感兴趣的可以尝试看看,这里就不进行展开)
         */
        DataSourceProxy dataSourceProxy = DataSourceProxyHolder.get().putDataSource((DataSource) invocation.getThis());
        Method method = invocation.getMethod();
        Object[] args = invocation.getArguments();
        Method m = BeanUtils.findDeclaredMethod(DataSourceProxy.class, method.getName(), method.getParameterTypes());
        if (null != m) {
            //执行目标方法时 实际执行的是代理对象的方法
            //代理对象也实现了DataSource接口
            return m.invoke(dataSourceProxy, args);
        } else {
            return invocation.proceed();
        }
    }

    @Override
    public Class<?>[] getInterfaces() {
        return new Class[]{SeataProxy.class};
    }
}

注:只有目标方法有对数据库的操作时,才会进入到数据源的代理逻辑;正常情况下,开启了分布式事务,就肯定会有对数据库的操作。

2 数据源代理逻辑

回想一下,jdbc对数据库的操作都是通过Statement来进行的,我们更熟悉的PreparedStatement也是Statement的子接口,而无论是Statement,还是PreparedStatement,都是通过Connection创建的。seata同时也提供了对Connection的代理--ConnectionProxy,同理,对PreparedStatement的代理--PreparedStatementProxy。

public class DataSourceProxy extends AbstractDataSourceProxy implements Resource {
 
    /**
     * 目标数据源--被代理的数据源
     */
    protected DataSource targetDataSource;
    

    /**
     * seata对Connection对象做了包装 持久层获取到的连接实际上是ConnectionProxy
     *
     * 在ConnectionProxy的父类AbstractConnectionProxyseata中
     * 对PreparedStatement做了包装 持久层获取到的实际上是PreparedStatementProxy
     * @return
     * @throws SQLException
     */
    @Override
    public ConnectionProxy getConnection() throws SQLException {
        Connection targetConnection = targetDataSource.getConnection();
        return new ConnectionProxy(this, targetConnection);
    }
}

在ConnectionProxy的父类AbstractConnectionProxy中,提供了创建StatementProxy和PreparedStatementProxy对象的方法。

public abstract class AbstractConnectionProxy implements Connection {
    

    public Statement createStatement() throws SQLException {
        Statement targetStatement = getTargetConnection().createStatement();
        return new StatementProxy(this, targetStatement);
    }
    
    /**
     * seata对PreparedStatement做了包装 持久层获取到的实际上是PreparedStatementProxy
     * @param sql
     * @return
     * @throws SQLException
     */
    @Override
    public PreparedStatement prepareStatement(String sql) throws SQLException {
        String dbType = getDbType();
        // support oracle 10.2+
        PreparedStatement targetPreparedStatement = null;
        if (RootContext.inGlobalTransaction()) {
            List<SQLRecognizer> sqlRecognizers = SQLVisitorFactory.get(sql, dbType);
            if (sqlRecognizers != null && sqlRecognizers.size() == 1) {
                SQLRecognizer sqlRecognizer = sqlRecognizers.get(0);
                if (sqlRecognizer != null && sqlRecognizer.getSQLType() == SQLType.INSERT) {
                    String tableName = ColumnUtils.delEscape(sqlRecognizer.getTableName(), dbType);
                    TableMeta tableMeta = TableMetaCacheFactory.getTableMetaCache(dbType).getTableMeta(getTargetConnection(),
                            tableName, getDataSourceProxy().getResourceId());
                    targetPreparedStatement = getTargetConnection().prepareStatement(sql, new String[]{tableMeta.getPkName()});
                }
            }
        }
        if (targetPreparedStatement == null) {
            targetPreparedStatement = getTargetConnection().prepareStatement(sql);
        }
        return new PreparedStatementProxy(this, targetPreparedStatement, sql);
    }

    
}

接下来就看PreparedStatementProxy的代理逻辑。

public class PreparedStatementProxy extends AbstractPreparedStatementProxy
    implements PreparedStatement, ParametersHolder {
   
    /**
     * Seata对PreparedStatement对象做了包装 所以在执行的时候将会调用到PreparedStatementProxy#execute()
     * @return
     * @throws SQLException
     */
    @Override
    public boolean execute() throws SQLException {
        //直接调用执行模板
        return ExecuteTemplate.execute(this, (statement, args) -> statement.execute());
    }
    
}

ExecuteTemplate.execute

public class ExecuteTemplate {
       
    //PreparedStatementProxy.execute调用的是本方法
    public static <T, S extends Statement> T execute(StatementProxy<S> statementProxy,
                                                     StatementCallback<T, S> statementCallback,
                                                     Object... args) throws SQLException {
        return execute(null, statementProxy, statementCallback, args);
    }
    
    public static <T, S extends Statement> T  execute(List<SQLRecognizer> sqlRecognizers,
                                                     StatementProxy<S> statementProxy,
                                                     StatementCallback<T, S> statementCallback,
                                                     Object... args) throws SQLException {
        /**
         *    RootContext.inGlobalTransaction()  判断此次操作是否是分布式事务  通过xid
         *    RootContext.requireGlobalLock() 判断是否加了GlobalLock注解
         */

        if (!RootContext.inGlobalTransaction() && !RootContext.requireGlobalLock()) {
            // Just work as original statement
            return statementCallback.execute(statementProxy.getTargetStatement(), args);
        }

        /**
         * 创建sql识别器 就是拿到现在需要执行的sql语句 判断是什么类型的sql
         */
        if (sqlRecognizers == null) {
            sqlRecognizers = SQLVisitorFactory.get(
                    statementProxy.getTargetSQL(),
                    statementProxy.getConnectionProxy().getDbType());
        }
        Executor<T> executor;
        //如果识别器没创建出来 就使用原生的执行器
        if (CollectionUtils.isEmpty(sqlRecognizers)) {
            executor = new PlainExecutor<>(statementProxy, statementCallback);
        } else {
            if (sqlRecognizers.size() == 1) {
                SQLRecognizer sqlRecognizer = sqlRecognizers.get(0);
                /**
                 * 在这里它会先 根据sql的类型生成不同的执行器 比如是一个insert 语句 那么就是InsertExecutor
                 */
                switch (sqlRecognizer.getSQLType()) {
                    case INSERT:
                        executor = new InsertExecutor<>(statementProxy, statementCallback, sqlRecognizer);
                        break;
                    case UPDATE:
                        executor = new UpdateExecutor<>(statementProxy, statementCallback, sqlRecognizer);
                        break;
                    case DELETE:
                        executor = new DeleteExecutor<>(statementProxy, statementCallback, sqlRecognizer);
                        break;
                    case SELECT_FOR_UPDATE:
                        executor = new SelectForUpdateExecutor<>(statementProxy, statementCallback, sqlRecognizer);
                        break;
                    default:
                        executor = new PlainExecutor<>(statementProxy, statementCallback);
                        break;
                }
            } else {
                executor = new MultiExecutor<>(statementProxy, statementCallback, sqlRecognizers);
            }
        }
        T rs;
        try {

            /**
             * select语句并且没有 for update  : PlainExecutor#execute()
             *  insert update delete 、select for update  : BaseTransactionalExecutor#execute()
             *
             */
            rs = executor.execute(args);
        } catch (Throwable ex) {
            if (!(ex instanceof SQLException)) {
                // Turn other exception into SQLException
                ex = new SQLException(ex);
            }
            throw (SQLException) ex;
        }
        return rs;
    }
}

2.1 处理加独占锁的sql

insert、update、delete、select for upadte -> BaseTransactionalExecutor#execute

public abstract class BaseTransactionalExecutor<T, S extends Statement> implements Executor<T> {
  
    public T execute(Object... args) throws Throwable {
        //保存xid
        if (RootContext.inGlobalTransaction()) {
            String xid = RootContext.getXID();
            statementProxy.getConnectionProxy().bind(xid);
        }

        //RootContext.requireGlobalLock()第一次为false
        statementProxy.getConnectionProxy().setGlobalLockRequire(RootContext.requireGlobalLock());
        //增删改  ==> AbstractDMLBaseExecutor.doExecute
        //select for update => SelectForUpdateExecutor.doExecute
        return doExecute(args);
    }
}

2.1.1 更新操作

insert、update、delete -> AbstractDMLBaseExecutor#doExecute

public abstract class AbstractDMLBaseExecutor<T, S extends Statement> extends BaseTransactionalExecutor<T, S> {

    public T doExecute(Object... args) throws Throwable {
        AbstractConnectionProxy connectionProxy = statementProxy.getConnectionProxy();
        //默认为自动提交
        if (connectionProxy.getAutoCommit()) {
            return executeAutoCommitTrue(args);
        } else {
            return executeAutoCommitFalse(args);
        }
    }


    protected T executeAutoCommitTrue(Object[] args) throws Throwable {
        ConnectionProxy connectionProxy = statementProxy.getConnectionProxy();
        try {

            //设置为手动提交
            connectionProxy.setAutoCommit(false);
            /**
             * execute():lambda表达式里的内容实在execute方法里面调用的
             */
            return new LockRetryPolicy(connectionProxy).execute(() -> {
                /**
                 * 执行前置快照
                 * 执行真正的业务逻辑
                 * 执行后置快照
                 * 准备undolog对象
                 */
                T result = executeAutoCommitFalse(args);
                /**
                 * 提交
                 * 1、注册分支事务
                 * 2、业务sql和undolog一起提交
                 */
                connectionProxy.commit();
                return result;
            });
        } catch (Exception e) {
            // when exception occur in finally,this exception will lost, so just print it here
            LOGGER.error("execute executeAutoCommitTrue error:{}", e.getMessage(), e);
            if (!LockRetryPolicy.isLockRetryPolicyBranchRollbackOnConflict()) {
                connectionProxy.getTargetConnection().rollback();
            }
            throw e;
        } finally {
            connectionProxy.getContext().reset();
            connectionProxy.setAutoCommit(true);
        }
    }


    protected T executeAutoCommitFalse(Object[] args) throws Exception {


        /**
         *  insert没有前置镜像
         *  uodate有前置镜像
         *  delete有前置镜像
         */
        //执行前置镜像  前图像表记录
        TableRecords beforeImage = beforeImage();
        //执行自己的业务逻辑
        T result = statementCallback.execute(statementProxy.getTargetStatement(), args);
        /**
         *  insert有后置镜像
         *  delete没有后置镜像
         *  update有后置镜像
         */
        //执行后置镜像 后图像表记录
        TableRecords afterImage = afterImage(beforeImage);

        //使用前置镜像和后置镜像生成Undolog对象
        prepareUndoLog(beforeImage, afterImage);

        //还没有提交
        return result;
    }
}

AbstractDMLBaseExecutor.LockRetryPolicy#execute

private static class LockRetryPolicy extends ConnectionProxy.LockRetryPolicy {
    

    public <T> T execute(Callable<T> callable) throws Exception {
        //读取配置文件中的配置 默认为true
        if (LOCK_RETRY_POLICY_BRANCH_ROLLBACK_ON_CONFLICT) {
             //调用父类的方法
            return doRetryOnLockConflict(callable);
        } else {
            //直接调用callable
            return callable.call();
        }
    } 
}

ConnectionProxy.LockRetryPolicy

public static class LockRetryPolicy {
    protected static final boolean LOCK_RETRY_POLICY_BRANCH_ROLLBACK_ON_CONFLICT = ConfigurationFactory
        .getInstance().getBoolean(ConfigurationKeys.CLIENT_LOCK_RETRY_POLICY_BRANCH_ROLLBACK_ON_CONFLICT, DEFAULT_CLIENT_LOCK_RETRY_POLICY_BRANCH_ROLLBACK_ON_CONFLICT);
    
    //todo:子类重写了该方法,比较重写的两个方法的逻辑
    public <T> T execute(Callable<T> callable) throws Exception {
        if (LOCK_RETRY_POLICY_BRANCH_ROLLBACK_ON_CONFLICT) {
            //执行lambda
            return callable.call();
        } else {
            return doRetryOnLockConflict(callable);
        }
    }

    protected <T> T doRetryOnLockConflict(Callable<T> callable) throws Exception {
        LockRetryController lockRetryController = new LockRetryController();
        while (true) {
            try {
                //实际调用的是那个lambda表达式
                return callable.call();
            } catch (LockConflictException lockConflict) {
                /**
                 * 捕获全局锁冲突异常
                 */
                onException(lockConflict);
                /**
                 * 重试机制 每次休眠m ms 休眠 n次后抛异常
                 */
                lockRetryController.sleep(lockConflict);
            } catch (Exception e) {
                onException(e);
                throw e;
            }
        }
    }
  }

callable.call()实际调用的是AbstractDMLBaseExecutor#executeAutoCommitTrue方法中定义的lambda表达式

/**
 * 执行前置快照
 * 执行真正的业务逻辑
 * 执行后置快照
 * 准备undolog对象
 */
T result = executeAutoCommitFalse(args);
/**
 * 提交
 * 1、注册分支事务
 * 2、业务sql和undolog一起提交
 */
connectionProxy.commit();
return result;
public abstract class AbstractDMLBaseExecutor<T, S extends Statement> extends BaseTransactionalExecutor<T, S> {

    protected T executeAutoCommitFalse(Object[] args) throws Exception {


       
        /**
         *  insert没有前置镜像 -> InsertExecutor#beforeImage()
         *  uodate有前置镜像 -> UpdateExecutor#beforeImage()
         *  delete有前置镜像 -> DeleteExecutor#beforeImage()
         */

        //执行前置镜像  前图像表记录
        TableRecords beforeImage = beforeImage();
        //执行自己的业务逻辑
        T result = statementCallback.execute(statementProxy.getTargetStatement(), args);
     
        /**
         *  insert有后置镜像 -> InsertExecutor#afterImage()
         *  update有后置镜像 -> UpdateExecutor#afterImage()
         *  delete没有后置镜像 -> DeleteExecutor#afterImage()
         */
        //执行后置镜像 后图像表记录
        TableRecords afterImage = afterImage(beforeImage);

        //使用前置镜像和后置镜像生成Undolog对象
        prepareUndoLog(beforeImage, afterImage);

        //还没有提交
        return result;
    }


    protected void prepareUndoLog(TableRecords beforeImage, TableRecords afterImage) throws SQLException {
        if (beforeImage.getRows().isEmpty() && afterImage.getRows().isEmpty()) {
            return;
        }

        ConnectionProxy connectionProxy = statementProxy.getConnectionProxy();

        TableRecords lockKeyRecords = sqlRecognizer.getSQLType() == SQLType.DELETE ? beforeImage : afterImage;
        //构建lockkey
        String lockKeys = buildLockKey(lockKeyRecords);
        connectionProxy.appendLockKey(lockKeys);
        //使用前置镜像和后置镜像构建undolog
        SQLUndoLog sqlUndoLog = buildUndoItem(beforeImage, afterImage);
        //将undolog暂存
        connectionProxy.appendUndoLog(sqlUndoLog);
    }
}

ConnectionProxy#commit

public class ConnectionProxy extends AbstractConnectionProxy {
   
    private final static LockRetryPolicy LOCK_RETRY_POLICY = new LockRetryPolicy();
    public void commit() throws SQLException {
        try {
            
            //ConnectionProxy.LockRetryPolicy.execute
            LOCK_RETRY_POLICY.execute(() -> {
                //提交
                doCommit();
                return null;
            });
        } catch (SQLException e) {
            throw e;
        } catch (Exception e) {
            throw new SQLException(e);
        }
    }
    
    
    
    private void doCommit() throws SQLException {
        if (context.inGlobalTransaction()) {
            /**
             * GlobalTransaction
             */
            processGlobalTransactionCommit();
        } else if (context.isGlobalLockRequire()) {
            /**
             * GlobalLock
             */
            processLocalCommitWithGlobalLocks();
        } else {
            targetConnection.commit();
        }
    }
    
    
    private void processGlobalTransactionCommit() throws SQLException {
        try {
            /**
             * 注册分支事务
             */
            register();
        } catch (TransactionException e) {
            /**
             * 全局锁冲突异常   如果抛出的是SqlException 最终会进行全局回滚(TransactionalTemplate#execute)
             */
            recognizeLockKeyConflictException(e, context.buildLockKeys());
        }
        try {
            /**
             * 向undolog表插入数据
             */
            UndoLogManagerFactory.getUndoLogManager(this.getDbType()).flushUndoLogs(this);
            /**
             * 本地数据和undolog表插入的数据一起提交
             */
            targetConnection.commit();
        } catch (Throwable ex) {
            LOGGER.error("process connectionProxy commit error: {}", ex.getMessage(), ex);
            /**
             * 向seata服务端报告一阶段情况
             * 如果本地事务提交失败告诉seata server
             */
            report(false);
            throw new SQLException(ex);
        }
        if (IS_REPORT_SUCCESS_ENABLE) {
            //向seata服务端报告一阶段情况
            report(true);
        }
        context.reset();
    }

    //注册分支事务
    private void register() throws TransactionException {
        if (!context.hasUndoLog() || context.getLockKeysBuffer().isEmpty()) {
            return;
        }
        
        //向seata服务端注册分支事务 将分支事务要锁定的资源传给seata-server,由seata-server判断锁冲突

        Long branchId = DefaultResourceManager.get().branchRegister(BranchType.AT, getDataSourceProxy().getResourceId(),
            null, context.getXid(), null, context.buildLockKeys());
        context.setBranchId(branchId);
    }

    //全局锁冲突异常判断
    private void recognizeLockKeyConflictException(TransactionException te, String lockKeys) throws SQLException {
        //如果是全局锁冲突异常
        if (te.getCode() == TransactionExceptionCode.LockKeyConflict) {
            StringBuilder reasonBuilder = new StringBuilder("get global lock fail, xid:");
            reasonBuilder.append(context.getXid());
            if (StringUtils.isNotBlank(lockKeys)) {
                reasonBuilder.append(", lockKeys:").append(lockKeys);
            }
            throw new LockConflictException(reasonBuilder.toString());
        } else {
            throw new SQLException(te);
        }

    }


    //报告一阶段情况
    private void report(boolean commitDone) throws SQLException {
        if (context.getBranchId() == null) {
            return;
        }
        int retry = REPORT_RETRY_COUNT;
        //重试机制
        while (retry > 0) {
            try {
                //报告一阶段提交成功 或 失败
                DefaultResourceManager.get().branchReport(BranchType.AT, context.getXid(), context.getBranchId(),
                    commitDone ? BranchStatus.PhaseOne_Done : BranchStatus.PhaseOne_Failed, null);
                return;
            } catch (Throwable ex) {
                LOGGER.error("Failed to report [" + context.getBranchId() + "/" + context.getXid() + "] commit done ["
                    + commitDone + "] Retry Countdown: " + retry);
                retry--;

                if (retry == 0) {
                    throw new SQLException("Failed to report branch status " + commitDone, ex);
                }
            }
        }
    }

}

2.1.2 查询操作

select for upadte -> SelectForUpdateExecutor.doExecute

public class SelectForUpdateExecutor<T, S extends Statement> extends BaseTransactionalExecutor<T, S> {
    
    public T doExecute(Object... args) throws Throwable {
        Connection conn = statementProxy.getConnection();
        //数据库的元数据
        DatabaseMetaData dbmd = conn.getMetaData();
        T rs;
        Savepoint sp = null;
        LockRetryController lockRetryController = new LockRetryController();
        boolean originalAutoCommit = conn.getAutoCommit();
        ArrayList<List<Object>> paramAppenderList = new ArrayList<>();
        //构建带for update的查询主键的sql
        //select id from t_order where username = 'zwj' for update
        String selectPKSQL = buildSelectSQL(paramAppenderList);
        try {
            if (originalAutoCommit) {
                /*
                 * In order to hold the local db lock during global lock checking
                 * set auto commit value to false first if original auto commit was true
                 */
                //设置自动提交为false
                conn.setAutoCommit(false);
            } else if (dbmd.supportsSavepoints()) { //判断数据库是否支持保存点
                /*
                 * In order to release the local db lock when global lock conflict
                 * create a save point if original auto commit was false, then use the save point here to release db
                 * lock during global lock checking if necessary
                 */
                sp = conn.setSavepoint();
            } else {
                throw new SQLException("not support savepoint. please check your db version");
            }

            while (true) {
                try {
                    // #870
                    // execute return Boolean
                    // executeQuery return ResultSet
                    //执行目标sql
                    rs = statementCallback.execute(statementProxy.getTargetStatement(), args);

                    // Try to get global lock of those rows selected
                    //执行查询主键的sql
                    TableRecords selectPKRows = buildTableRecords(getTableMeta(), selectPKSQL, paramAppenderList);
                    //根据查询出来的主键构建lockkey
                    String lockKeys = buildLockKey(selectPKRows);
                    if (StringUtils.isNullOrEmpty(lockKeys)) {
                        break;
                    }


                    if (RootContext.inGlobalTransaction()) {//判断当前方法是否加了@GlobalTransaction注解
                        //do as usual
                        /**
                         * 向seata 服务端发送请求 检查锁是否被占用
                         */
                        statementProxy.getConnectionProxy().checkLock(lockKeys);
                    } else if (RootContext.requireGlobalLock()) {
                        //check lock key before commit just like DML to avoid reentrant lock problem(no xid thus can
                        // not reentrant)
                        statementProxy.getConnectionProxy().appendLockKey(lockKeys);
                    } else {
                        throw new RuntimeException("Unknown situation!");
                    }
                    break;
                } catch (LockConflictException lce) {
                      //捕获锁冲突异常
                    if (sp != null) {
                        conn.rollback(sp);
                    } else {
                        conn.rollback();
                    }
                    //睡眠一段时间后重试
                    lockRetryController.sleep(lce);
                }
            }
        } finally {
            if (sp != null) {
                try {
                    conn.releaseSavepoint(sp);
                } catch (SQLException e) {
                    if (LOGGER.isWarnEnabled()) {
                        LOGGER.warn("{} does not support release save point, but this is not a error.", getDbType());
                    }
                }
            }
            if (originalAutoCommit) {
                conn.setAutoCommit(true);
            }
        }
        return rs;
    }


    
    //构建查询主键的sql
    private String buildSelectSQL(ArrayList<List<Object>> paramAppenderList) {
        SQLSelectRecognizer recognizer = (SQLSelectRecognizer)sqlRecognizer;
        StringBuilder selectSQLAppender = new StringBuilder("SELECT ");  //select
        selectSQLAppender.append(getColumnNameInSQL(getTableMeta().getPkName())); // select id(主键)
        selectSQLAppender.append(" FROM ").append(getFromTableInSQL());// select id from t_order
        String whereCondition = buildWhereCondition(recognizer, paramAppenderList);
        if (StringUtils.isNotBlank(whereCondition)) {
            selectSQLAppender.append(" WHERE ").append(whereCondition);//select id from t_order where username = 'zwj'
        }
        selectSQLAppender.append(" FOR UPDATE");////select if from t_order where username = 'zwj' for update
        return selectSQLAppender.toString();
    }

}

2.2 处理不加锁的sql

select语句并且不加for update -> PlainExecutor#execute(

public class PlainExecutor<T, S extends Statement> implements Executor<T> {
    private StatementProxy<S> statementProxy;
    public T execute(Object... args) throws Throwable {
        //直接指向
        return statementCallback.execute(statementProxy.getTargetStatement(), args);
    }
}

总结 执行目标方法的流程: 数据源代理逻辑:

1、生成前置镜像
2、执行目标sql
3、生成后置镜像
- insert:没有前置镜像,有后置镜像
- update:既有前置镜像,也有后置镜像
- delete:有前置镜像,无后置镜像
4、使用前置镜像和后置镜像生成undolog
5、注册分支事务 seata-server会进行全局锁冲突异常检查
6、将生成的undolog插入到undolog表中
7、报告一阶段情况