Spring 下,关于动态数据源的事务问题的探讨
点击上方蓝色“方志朋”,选择“设为星标”
回复“666”获取独家整理的学习资料!
作者:青石路
cnblogs.com/youzhibing/p/12671004.html
前情回顾
看着文章的标题,不知道大家能否想到具体是什么问题,如果你有点懵,那就对了!(你不懵的话我这篇文章就没存在的意义了,嘿嘿)
在给大家指出具体是什么问题时,我们先来回顾一些内容
Spring 事务原理
相信大家对这个都能说上来一些,Spring 事务是 Spring AOP 的一种具体应用,底层依赖的是动态代理
大致流程类似如下
通过代理对象来调用目标对象,而在代理对象中有事务相关的增强处理
具体细节可参考以下文章
https://www.cnblogs.com/youzhibing/p/6414780.html
https://www.cnblogs.com/youzhibing/p/6690341.html
https://www.cnblogs.com/youzhibing/p/12071391.html
Spring 动态数据源原理
原理解密 → Spring AOP 实现动态数据源(读写分离),底层原理是什么中已经详细介绍过了,流程大体如下
Spring AOP → 将我们指定的 lookupKey 放入 ThreadLocal
ThreadLocal → 线程内共享 lookupKey
DynamicDataSource → 对多数据源进行封装,根据 ThreadLocal 中的 lookupKey 动态选择具体的数据源
有什么问题
既然事务和动态数据源都是 Spring AOP 的具体应用,那么代理就存在先后顺序了
要么是
要么是
我们来看看这两者有什么区别
事务在前,动态数据源在后
此时,事务的前置增强处理会先生效,那么此时开始事务获取的 Connection 从哪来 ?肯定是从 DynamicDataSource 来,因为我们给事务管理器配置的就是它
@Beanpublic PlatformTransactionManager transactionManager(@Qualifier("dynamicDataSource") DataSource dynamicDataSource) {// 配置事务管理, 使用事务时在方法头部添加@Transactional注解即可return new DataSourceTransactionManager(dynamicDataSource);}
既然是从 DynamicDataSource 获取的 Connection,那 DynamicDataSource 根据 lookupKey 获取 Connection 的时候,会从 masterDataSource 数据源获取还是从 slaveDataSource 数据源获取 ?因为此时还未将 lookupKey 绑定到当前线程,那么 DynamicDataSource 会从默认数据源获取,而我们配置的默认数据源是 slaveDataSource
/*** 获取当前线程的数据源* @return*/public static DataSourceType getDataSourceType(){return HOLDER.get() == null ? DataSourceType.SLAVE : HOLDER.get();}
说白了,此时的动态数据源对事务不生效,事务始终从默认数据源获取 Connection,而没有动态的效果,这就是问题了
Talk is cheap. Show me the code,我们来看看是不是真的如上所说
192.168.0.112 正是我们的从库,对应的就是我们的默认数据源 slaveDataSource
动态数据源在前,事务在后
此时,动态数据源的前置增强会先执行,DynamicDataSource 需要的 lookupKey 会先于事务绑定到当前线程,那么事务从 DynamicDataSource 获取 Connection 的时候就能根据当前线程的 lookupKey 来动态选择 masterDataSource 还是 slaveDataSource
此种情况是没有问题的
解决问题
总结下问题:如何保证事务中的动态数据源也有动态的效果,也就是如何保证动态数据源的前置增强先于事务
我们知道 Spring AOP 是能够指定顺序的,只要我们显示的指定动态数据源的 AOP 先于 事务的 AOP 即可;如何指定顺序,常用的方式是实现 Order 接口,或者使用 @Order 注解,Order 的值越小,越先执行,所以我们只需要保证动态数据源的 Order 值小于事务的 Order 值即可
我们先来看看事务的 Order 值默认是多少,在 EnableTransactionManagement 注解中
/*** Indicate the ordering of the execution of the transaction advisor* when multiple advices are applied at a specific joinpoint.* <p>The default is {@link Ordered#LOWEST_PRECEDENCE}.*/int order() default Ordered.LOWEST_PRECEDENCE;
默认是最低级别(值非常大),那么我们只需要保证动态数据源的 Order 比这个值小就好,我们就取 1
@Component@Slf4j@Order(1)public class DynamicDataSourceAspect {
我们在来看看是否真的可行
已经不是默认的 slaveDataSource ,而是我们指定的 masterDataSource(通过 @MasterSlave(MASTER) 指定)
至此,相信大家已经弄清楚了有什么问题,以及如何解决它
什么,还没理解 ?你过来,我保证不打死你
总结
1、不只是动态数据源和事务,只要涉及到多个 AOP,就可能会有顺序问题,这是值得大家注意的
2、相关约束
主数据库执行 INSERT UPDATE DELETE 操作,可能还有部分 SELECT 操作(主从同步多少有延时)
从数据库只执行 SELECT 操作
默认数据源最好设置成主数据源,防止粗心将更新操作执行到了从数据库;楼主之所以设置成从数据源,是考虑到绝大多数数据库操作是查询,这样可以减少代码量;具体怎么选,需要大家结合实际情况来决定
热门内容:
道友自诉:入职中软一个月(外包华为)就离职了!
腾讯推出高性能 RPC 开发框架
再见了SpringMVC,这个框架有点厉害,甚至干掉了Servlet!
原来 Elasticsearch 还可以这么理解
干掉Navicat:正版,MySQL官方客户端真香!
最近面试BAT,整理一份面试资料《Java面试BAT通关手册》,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。获取方式:点“在看”,关注公众号并回复 666 领取,更多内容陆续奉上。
明天见(。・ω・。)
Spring 下,关于动态数据源的事务问题的探讨相关推荐
- java多个数据库数据进行访问_通过Spring Boot配置动态数据源访问多个数据库的实现代码...
之前写过一篇博客<Spring+Mybatis+Mysql搭建分布式数据库访问框架>描述如何通过Spring+Mybatis配置动态数据源访问多个数据库.但是之前的方案有一些限制(原博客中 ...
- mysql 多数据源访问_通过Spring Boot配置动态数据源访问多个数据库的实现代码
之前写过一篇博客<Spring+Mybatis+Mysql搭建分布式数据库访问框架>描述如何通过Spring+Mybatis配置动态数据源访问多个数据库.但是之前的方案有一些限制(原博客中 ...
- Spring(AbstractRoutingDataSource)实现动态数据源切换
参考:http://linhongyu.blog.51cto.com/6373370/1615895 一.前言 近期一项目A需实现数据同步到另一项目B数据库中,在不改变B项目的情况下,只好选择项目A中 ...
- Spring(AbstractRoutingDataSource)实现动态数据源切换--转载
原始出处:http://linhongyu.blog.51cto.com/6373370/1615895 一.前言 近期一项目A需实现数据同步到另一项目B数据库中,在不改变B项目的情况下,只好选择项目 ...
- Spring Boot使用动态数据源
文章目录 前言 一.什么是动态数据源 二.动态数据源实现 1.实现原理 2.实现过程 前言 有这样一个场景,现在要开发一个数据API功能,用户自己编写数据源脚本,在界面任意选择一个数据源,可选择的数据 ...
- SpringBoot+MyBatis(动态数据源/分布式事务XA(Atomikos))
快速集成工具,欢迎打脸 说明 适用环境:SpringBoot / MyBatis / Atomickos 特性: 多数据源,动态切换 多数据源,XA分布式事务支持(需引入Atomickos) 仅支持 ...
- spring 动态数据源切换实例
我们很多项目中业务都需要涉及到多个数据源,最简单的做法就是直接在java代码里面lookup需要的数据源,但是这样的做法很明显耦合度太高了, 而且当逻辑流程不够严谨的时候就会出现各种大家不愿意看到的问 ...
- spring 动态数据源
1.动态数据源: 在一个项目中,有时候需要用到多个数据库,比如读写分离,数据库的分布式存储等等,这时我们要在项目中配置多个数据库. 2.原理: (1).spring 单数据源获取数据连接过程: ...
- 我已经把它摸的透透的了!!!Spring 动态数据源设计实践,全面解析
[ Spring 动态数据源 动态数据源是什么?它能解决什么??? 在实际的开发中,同一个项目中使用多个数据源是很常见的场景.比如,一个读写分离的项目存在主数据源与读数据源. 所谓动态数据源,就是通过 ...
最新文章
- 自定义audio样式
- 用InstallShield9打包 vb6+水晶报表中文版9.2 [转]
- UVa 10061 How many zero's and how many digits?
- 面试题解析:1 Java中switch语句可以作用在enum上的测试
- 大数据分析需注意哪些问题
- 计算机开放电子书 2016 归档
- dell服务器卸载系统,如何通过 iDRAC9 装载和卸载驱动程序包
- linux启动tomcat后,浏览器访问不到
- 代写品牌故事四步写作方法
- jsp实现文件的上传
- 呼叫中心系统的基本构成和二次开发思路
- Python-股票-图表显示主要财务指标
- 甲方、乙方、监理三者之间的关系及其在项目管理过程中的若干事项
- 青软集团U+新工科智慧云平台助力西北民族大学编程竞赛成功举办!
- MySQL的limit分页,为什么越往后翻越慢,怎么解决?
- 12星座的出生年月日性格_出生的人的星座是什么十二星座出生年月日
- SpringBoot实现音乐网站解析(支持腾讯、网易、小米、酷狗)
- emacs 24安装ecb与cedet
- 2021美赛数据分析全网首发(R语言 )
- Oracle数据库中stragg()函数,在瀚高数据库中如何替换使用?