fescar

Fescar - RM undoLog的介绍

2019-02-18  本文已影响32人  晴天哥_王志

开篇

 这篇文章的目的是介绍Fescar当中回滚日志undoLog的数据结构,为后续RM执行回滚动作rollback打下基础,因为undoLog涉及的数据结构用源码表示起来比较简单通俗易懂,所以直接根据源码进行讲解。

undoLog源码介绍

public class TableRecords {
    // 表元数据记录
    private TableMeta tableMeta;
    // 表名
    private String tableName;
    // 查询获得的行记录
    private List<Row> rows = new ArrayList<Row>();
}

public class Row {
    // 表的行记录其实表中列字段的集合,Field是column字段。
    private List<Field> fields = new ArrayList<Field>();
}

public class Field {

    // 列名
    public String name;

    private KeyType keyType = KeyType.NULL;

    // 列的字段类型。
    public int type;

    // 列的值
    public Object value;
}

说明:

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

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

        ConnectionProxy connectionProxy = statementProxy.getConnectionProxy();

        // 生成TC的全局锁对象lockKeys  
        TableRecords lockKeyRecords = sqlRecognizer.getSQLType() == SQLType.DELETE ? beforeImage : afterImage;

        // 根据SQL类型区分生成锁字段的原始素材
        String lockKeys = buildLockKey(lockKeyRecords);

        // 将锁字段保存到connectionProxy的维度
        connectionProxy.appendLockKey(lockKeys);

        // 准备SQLUndoLog
        SQLUndoLog sqlUndoLog = buildUndoItem(beforeImage, afterImage);

       // 将回滚日志保存到connectionProxy的维度
        connectionProxy.appendUndoLog(sqlUndoLog);
    }
}

说明:

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

    protected String buildLockKey(TableRecords rowsIncludingPK) {
        if (rowsIncludingPK.size() == 0) {
            return null;
        }
        StringBuilder sb = new StringBuilder();
        sb.append(rowsIncludingPK.getTableMeta().getTableName());
        sb.append(":");

        boolean flag = false;
        for (Field field : rowsIncludingPK.pkRows()) {
            if (flag) {
                sb.append(",");
            } else {
                flag = true;
            }
            sb.append(field.getValue());
        }
        return sb.toString();
    }
}

说明:

public class SQLUndoLog {
    // SQL的类型
    private SQLType sqlType;
    // 表名
    private String tableName;
    // 执行前镜像
    private TableRecords beforeImage;
    // 执行后镜像
    private TableRecords afterImage;
}


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

    protected SQLUndoLog buildUndoItem(TableRecords beforeImage, TableRecords afterImage) {
        SQLType sqlType = sqlRecognizer.getSQLType();
        String tableName = sqlRecognizer.getTableName();

        SQLUndoLog sqlUndoLog = new SQLUndoLog();
        sqlUndoLog.setSqlType(sqlType);
        sqlUndoLog.setTableName(tableName);
        sqlUndoLog.setBeforeImage(beforeImage);
        sqlUndoLog.setAfterImage(afterImage);

        return sqlUndoLog;
    }
}

说明:

重点

 个人认为重点在于undoLog的lockKey的生成逻辑以及保存的容器在于connectionProxy对象。

上一篇 下一篇

猜你喜欢

热点阅读