开发者社区> 晴天哥> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

Fescar - RM undoLog的介绍

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

开篇

 这篇文章的目的是介绍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;
}

说明:

  • 介绍UndoLog对象之前必须先了解构建UndoLog的原始记录beforeImage和afterImage对象。
  • TableRecords beforeImage = beforeImage()中TableRecords保存SQL执行前后数据镜像。
  • TableRecords顾名思义就是表当中的数据记录,保存从数据表中查询得到的行记录。
  • TableRecords中的List是行记录的集合。
  • Row中的List是单行当中的列字段column。
  • Field是描述单列的数据结构,包含列的字段名,字段类型,字段值等。


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);
    }
}

说明:

  • 根据SQL类型区分生成锁字段的原始素材beforeImage或afterImage。
  • 将锁字段保存到connectionProxy的维度
  • 准备SQLUndoLog,通过beforeImage或afterImage。
  • 将回滚日志sqlUndoLog保存到connectionProxy的维度


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();
    }
}

说明:

  • 锁字段的生成逻辑是表名:primaryKey的列值。
  • 锁字段的生成逻辑是表名加pk的值。
  • 关注外层的for循环,如果变更多条记录即多个row记录,就拼接所有row记录的pk的值。


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;
    }
}

说明:

  • SQLUndoLog的数据结构如上所示,包括SQL类型、表名、执行前后镜像。
  • buildUndoItem的构建UndoItem的逻辑就是保存上述提到的基础数据。


重点

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

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
mac上安装Homebrew及一些报错的处理
mac上安装Homebrew及一些报错的处理
30 0
2300+字!在不同系统上安装Docker!看这一篇文章就够了
辰哥准备出一期在Docker跑Python项目的技术文,比如在Docker跑Django或者Flask的网站、跑爬虫程序等等。
50 0
mac上安装Homebrew及一些报错的处理
mac上安装Homebrew及一些报错的处理
80 0
OpenGrok安装配置 - MAC篇
# OpenGrok安装配置 - MAC篇 ## 简介 OpenGrok一个快速、便于使用的源代码搜索与对照引擎。它帮助你搜索,对照,定位你的源代码树。它能够明白各种程序文件格式和版本控制历史记录如SCCS,RCS,CVS与Subversion。OpenGrok是OpenSolaris操作系统源文件浏览和搜索的工具。 使用起来非常非常方便,代码搜索速度超快,没用过的同学可以自行感受一下(网
7956 0
uva11825Hacker's Crackdown
题意:题意很费解,大意是有N台电脑,每台电脑有N(N
595 0
+关注
晴天哥
专注java技术,热爱长跑和阅读开源代码 邮箱 lebron374@163.com
403
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载