Seata 分布式事务 随记

官网

AT模式:https://github.com/seata/seata/wiki/AT-Mode

流程解释:http://seata.io/zh-cn/docs/overview/what-is-seata.html

AT流程图解

https://www.cnblogs.com/smileIce/p/11200829.html

注意

1、表必须有主键。

2、截止到0.9版不支持联合主键。可以用自增id做主键+联合主键改为唯一键。

3、UNDO_LOG表每个数据库都创建,记录全局事务Xid+表名+执行前/后镜像 等信息用于回滚。

     在全局事务的每个子事务执行时,一起本地提交UNDO_LOG表(和本地业务在同一个事务中)。

4 、AT模式下,Seata为全局事务涉及到的数据行在SeataServer中建立全局锁(表名+主键),写操作提交时需要先拿到此行数据的全局锁,在全局事务提交时才会释放全局锁。通过全局锁(表+主键)保证同一行数据要在一个全局事务完成后,其他全局事务才能写操作。

5、全局事务隔离性默认是读未提交。因为一个全局事务的每个子事务在执行后都是立即本地提交的,但是此时全局事务并未提交,而且还可能会回滚。但是此时其他查询会读到已经本地提交的数据。

官方的全局读已提交隔离性通过select for update申请全局锁实现

官方对隔离性的说明:https://github.com/seata/seata/wiki/AT-Mode

 

回滚实例,原代码逻辑解析,bug坑分析

https://blog.csdn.net/flyfhj/article/details/99456100

检验开始
AbstractUndoExecutor.java的dataValidationAndGoOn方法

protected boolean dataValidationAndGoOn(Connection conn) throws SQLException {
    //数据修改前镜像
    TableRecords beforeRecords = sqlUndoLog.getBeforeImage();
    //数据修改后镜像
    TableRecords afterRecords = sqlUndoLog.getAfterImage();
    //如果修改前镜像=修改后镜像,说明数据没有变更,无须回滚
    if (DataCompareUtils.isRecordsEquals(beforeRecords, afterRecords)) {
        return false;
    }
    //查找当前镜像
    TableRecords currentRecords = queryCurrentRecords(conn);
    //如果当前镜像**不等于**修改后镜像,继续对比
    if (!DataCompareUtils.isRecordsEquals(afterRecords, currentRecords)) {
            //如果当前镜像**等于**修改前镜像,说明数据没有变更,无须回滚,否则为脏数据直接抛出异常
            if (DataCompareUtils.isRecordsEquals(beforeRecords, currentRecords)) {

总结3点:
1、修改前镜像等于修改后镜像,说明数据没有变更,无须回滚
2、当前镜像等于修改后镜像,则说明当前数据需要进行回滚
3、当前镜像不等于修改后镜像且当前镜像等于修改前镜像,说明数据无变更,无须回滚

举例:

修改前镜像 修改后镜像 当前镜像 是否回滚
5000 4700 5000 不回滚
5000 4700 4700 回滚
5000 5000 *** 不回滚
5000 4700 4400 脏数据&&不回滚

 

集成NACOS

https://blog.csdn.net/qq_27376871/article/details/91570779

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章