seata源码分析之-AT模式写隔离

seata源码分析之-AT模式写隔离

AT模式写隔离

在这里插入图片描述
当我们看到上面的图的时候可能不太明白这个具体是怎么做的,所以今天就来源码看下。
首先是获取全局锁,那这个到底是什么锁呢,我们来看TA模式的ConnectionProxyprocessGlobalTransactionCommit方法:
在这里插入图片描述
注册的时候会去注册锁,其实有点像分布式锁,谁先注册了谁就占着了,然后其他的就要重试:
在这里插入图片描述
其实这把锁哪里来的,就是在准备回滚日志的时候生成的,表名_主键ID
在这里插入图片描述
如果发现注册有锁冲突,说明已经被别人抢到锁了,回头就抛recognizeLockKeyConflictException异常:
在这里插入图片描述
这个异常一直抛出去,直到外面有捕获的,睡眠一定时间重试,直到超时抛出LockWaitTimeoutException异常:
在这里插入图片描述
然后服务端提交后会释放锁,具体可以看服务端代码,这个就不细说了:
在这里插入图片描述
现在应该能大致看明白那个图了把,其实就是谁先注册谁就获得锁,然后做事务,提交了才会释放锁,如果注册发现有锁了,就只能不断的尝试,直到能注册位置,这样就进行了写隔离,同一时刻就只能有一个事务对同一个数据进行修改。

AT模式读隔离

在这里插入图片描述
这张图说的是读隔离,默认的是读未提交,如果要进行读已提交的话也可以用全局锁:
sql中有SELECT FOR UPDATE语句,执行器就是SelectForUpdateExecutor,可以看到查询的时候会检查全局锁,不能获得就会重试:

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

                    // Try to get global lock of those rows selected
                    TableRecords selectPKRows = buildTableRecords(getTableMeta(), selectPKSQL, paramAppenderList);
                    String lockKeys = buildLockKey(selectPKRows);//构建全局锁
                    if (StringUtils.isNullOrEmpty(lockKeys)) {
                        break;
                    }

                    if (RootContext.inGlobalTransaction() || RootContext.requireGlobalLock()) {
                        // Do the same thing under either @GlobalTransactional or @GlobalLock, 
                        // that only check the global lock  here.
                        statementProxy.getConnectionProxy().checkLock(lockKeys);//检查全局锁
                    } else {
                        throw new RuntimeException("Unknown situation!");
                    }
                    break;
                } catch (LockConflictException lce) {
                    if (sp != null) {
                        conn.rollback(sp);
                    } else {
                        conn.rollback();
                    }
                    // trigger retry
                    lockRetryController.sleep(lce);//重试
                }
            }

TC查询锁是否存在:
在这里插入图片描述
其实就一个简单的例子,比如你想查询一个数据,但是你没在任何全局事务中,但是怕有其他全局事务在修改,你查出来的数据有问题,那怎么办呢,你就可以在查询的方法上用@GlobalLock,其实就是一个读隔离。
在这里插入图片描述

好了,今天就到这里了,大致的说下AT的读写隔离,细节的还要自己去看,希望对学习理解有帮助,大神看见勿喷,仅为自己的学习理解,能力有限,请多包涵。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值