Seata执行整体流程(AT模式)| Seata源码 - 自动配置、数据库代理 | AT和XA的区别

本文详细解读了Seata分布式事务的整体流程,包括TM注册、全局事务拦截、本地事务执行与TM通信,以及AT与XA模式的区别。重点介绍了数据库代理、事务提交/回滚机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

0. 相关术语:
  • TC一般指seata-server
  • TM一般就是事务操作接口入口的服务,也就是标注@GlobalTransactional的服务
  • RM一般就是涉及整体事务操作的服务
  • 比如确认订单加积分,订单服务就作为TM和RM,积分服务就作为RM

在这里插入图片描述

实验代码可见GitHub

在这里插入图片描述

1. 整体流程:

在这里插入图片描述

  1. TM、RM注册
  2. 初始化后置处理器方法中引入全局事务拦截器GlobalTransactionalInterceptor
  3. 请求时调用拦截器invoke方法,TM发起全局事务
  4. RM通过数据库代理执行本地事务
  • 解析SQL - 关闭自动提交 - 查询前镜像 - 执行业务SQL - 查询后镜像 - 根据前后镜像构建undo_log - 提交写入undo_log - 手动提交业务SQL
  1. TM发送commit/rollback给TC
  2. 分支事务提交/回滚:
  • 如果提交:采用异步线程去删除undo_log,一阶段已经提交本地事务了
  • 如果回滚:根据分支事务id和全局事务xid获取undo_log(数据库表有唯一索引),然后进行反向补偿,删除undo_log
1.1. TM、RM注册
  • 自动配置类SeataAutoConfiguration引入GlobalTransactionScanner
  • GlobalTransactionScanner实现InitializingBean,在IOC创建bean时,会调用afterPropertiesSet方法
  • 内部调用initClient方法中,进行TM、RM注册

在这里插入图片描述

1.2. 引入全局事务拦截器GlobalTransactionalInterceptor
  • GlobalTransactionScanner继承了AbstractAutoProxyCreator,是个后置处理器,并重写了wrapIfNecessary方法

在这里插入图片描述

  • 在IOC创建bean时,会调用postProcessAfterInitialization后置处理器方法,然后执行wrapIfNecessary
  • 引入全局事务拦截器GlobalTransactionalInterceptor

在这里插入图片描述

1.3. 请求时调用拦截器invoke方法,TM发起全局事务
  • 当发起请求,再调用Controller时会先调用拦截器,也就是全局事务拦截器GlobalTransactionalInterceptor的invoke()方法
  • 如果要发起全局事务就调用handleGlobalTransaction方法

在这里插入图片描述

  • 调用transactionalTemplate.execute方法,进行事务创建/加入,发起全局事务

在这里插入图片描述

beginTransaction是一个模板方法,tx.begin发起全局事务会生成和绑定全局事务xid

在这里插入图片描述

1.4. RM通过数据库代理执行本地事务:
  • beginTransactionf发起全局事务后,business.execute()最终反射调用@GlobalTransactional注解的方法
  • 当业务方法中进行数据库操作时,seata通过数据库代理执行
  • 解析SQL - 关闭自动提交 - 查询前镜像 - 执行业务SQL - 查询后镜像 - 根据前后镜像构建undo_log - 提交写入undo_log - 手动提交业务SQL

在这里插入图片描述

1.4 .1. 启用数据库自动代理:
  • 此处seata-all是1.4.2版本,需要在启动类加上@EnableAutoDataSourceProxy注解
  • 最终是会注册两个bean:SeataDataSourceBeanPostProcessor、SeataAutoDataSourceProxyCreator

在这里插入图片描述

  • bean创建SeataDataSourceBeanPostProcessor时,调用后置处理器方法进行数据源代理(DataSourceProxy)

在这里插入图片描述

  • 数据源获取Connection 的时候,也会对Connection 进行代理(ConnectionProxy):

在这里插入图片描述

  • 通过ConnectionProxy获取statement时(父类AbstractConnectionProxy方法),seata也对statement进行了代理;

在这里插入图片描述

1.4 .2. 数据源代理执行SQL:
  • seata对数据源到statement都进行了代理,当statement执行SQL时,最终调用ExecuteTemplate.execute核心方法

在这里插入图片描述

调用链:

  • executor.execute → io.seata.rm.datasource.exec.BaseTransactionalExecutor#doExecute → executeAutoCommitTrue
  • executeAutoCommitFalse(args) → connectionProxy.commit(); → doCommit → processGlobalTransactionCommit

执行流程:

  • 解析 SQL:得到 SQL 的类型、表、条件等相关的信息
  • 关闭自动提交
  • 查询前镜像(原始数据):根据解析得到的条件信息,生成查询语句,定位数据。
  • 执行业务 SQL
  • 查询后镜像(修改后数据):根据前镜像的结果,通过 主键 定位数据。
  • 构建undo_log日志
  • 提交写入undo_log日志
  • 手动提交业务SQL,本地事务也提交了,但全局事务没有

在这里插入图片描述
在这里插入图片描述

1.5 TM发送commit/rollback给TC:
  • RM执行完本地事务(也就是业务方法执行完),都执行正常TM就发送commit给TC,否则就rollback
  • 通过全局事务xid控制commit/rollback

在这里插入图片描述

1.7 分支事务提交/回滚:
  • 如果提交:采用异步线程去删除undo_log,一阶段已经提交本地事务了
  • 如果回滚:根据分支事务id和全局事务xid获取undo_log(数据库表有唯一索引),然后进行反向补偿,删除undo_log
  • 详情可以见参考链接:seata客户端二阶段分支事务的提交和回滚
2. AT和XA的区别:

 核心区别在于:

  • AT模式一阶段本地事务提交完后会提交本地事务;
  • XA模式要在所有的本地事务执行完成后,TC才发送指令让所有的RM提交事务、释放本地锁。
  • 所以XA的性能会低,但能保证强一致性效果
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值