概述
在多数据源的配置下,业务中经常遇到在一个被本地事务包裹的save/edi
方法中需要查询另一个数据源的数据;
直接查询会提示table
不存在,这是因为一个事务和一个mysql
连接是绑定的,mysql
的连接背后包含了数据库信息,直接调用还是在当前连接上调用的;
这里可以利用事务的单一connection
连接这个特性,曲线解决这个问题;
环境
mysql8
springboot2.7.4
方法
方法很简单,就是在查询另一个数据源时,开启一个新事务就行了
public class LogicDeleteTest {@Transactionalpublic void asLinkDiscountServiceLogicDelete(){//获取aop代理类((LogicDeleteTest)AopContext.currentProxy()).findDataFromOtherDataSource();}@Transactional(propagation = Propagation.REQUIRES_NEW)public Object findDataFromOtherDataSource(){return null;}}
源码分析
spring
的事务整体流程大致如下;
可以实际debug
一波看下多数据源下,使用上述2
个事务后spring
对事务的执行流程;
- 获取事务的属性(
@Transactional
注解中的配置) - 加载配置中的
TransactionManager
. - 获取收集事务信息
TransactionInfo
- 执行目标方法
- 出现异常,尝试处理。
- 清理事务相关信息
- 提交事务
简单起见可以从这个源码class方法中入手
org.springframework.transaction.interceptor.TransactionAspectSupport#invokeWithinTransaction
最后在这个方法中开启了新事务,并获取了一个新连接
org.springframework.jdbc.datasource.DataSourceTransactionManager#doBegin
再往下就是根据注解上的数据源name获取对应的数据源,获取到对应数据源后,之后的流程就和普通查询流程一样了
com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder#peek
com.baomidou.dynamic.datasource.DynamicRoutingDataSource#getDataSource