Atomikos分布式事务中切换数据源

Atomikos分布式事务中切换数据源_第1张图片


昨天的分析痛快淋漓,环环相扣,分享后好评如潮。然而内心却有隐隐疑虑,不知从何而来。本没有计划再写续集,然而一觉醒来,已然恍然大悟。

我们边看RIO开幕式,边细细道来。


1. 问题由来


昨日我们庖丁解牛,深入DataSourceTransactionManager源码,解开事务与动态数据源切换之谜,然而在代码测试中,我们遗留了一个致命隐患,

时而阴阴作痛,让人无眠。有趣的是,发文后超400UV竟然无人发觉,又或是无留言功能的弊端?哈哈
在系列I中,我们最终实现了在一个事务方法中,支持动态切换,访问多个数据源,并且似乎最终事务也实现了提交,会滚等。但,我们在调试中

碰到了一个问题,却始终隐隐困扰,如下。

Atomikos分布式事务中切换数据源_第2张图片

系列I中,我们在第一个数据库操作后,进行回滚,一切正常。但,当我们把异常抛出放到第二个数据库操作后:


Atomikos分布式事务中切换数据源_第3张图片

可以看出,日志还有一条数据打出来。


Atomikos分布式事务中切换数据源_第4张图片

数据库中也可以看出,db1回滚了,但db2没有回滚!


2. 原因解析


其实,昨天系列1中我们隐隐不安的原因,也正是我们剖析源代码,并且日志也可以看出,我们使用的是DataSourceTransactionManager

事务管理器。而常识告诉我们,DataSourceTransactionManager只能管理一个数据源的事务,请问如何能管理多个数据库呢??另外,

上边的无法完全会滚也再次证明我们的观点。可以看出,DataSourceTransactionManager始终只是管理着第一个数据源,所以才有当第

一个操作执行完抛出异常,db1可以回滚。但是,当两个操作都执行完后,再抛出异常,只有上边图文中的db1回滚,db2没有回滚。
现在真相大白!
另外,据此,我们继续推论,其实如果在注解事务下,强制修改DAO数据源,一样可以实现访问多个数据库,但同样无法真正支撑事务。

事实也正如此!


3. 解决方案


问题清楚了,请问怎么破?
当然引入分布式中间件了,JTA登场。我们采用轻量级非容器分布式事务中间件:atomikos。

XML配置:
Atomikos分布式事务中切换数据源_第5张图片
引入分布式事务管理器后,我们再来看一下,代码无须改动。

Atomikos分布式事务中切换数据源_第6张图片
数据库也正常,db1,db2都有数据插入。
Atomikos分布式事务中切换数据源_第7张图片

我们来重点看一下两种异常的回滚:

Atomikos分布式事务中切换数据源_第8张图片
db1,db2也正常,都没有插入。 我们看一下关键的异常2回滚。 Atomikos分布式事务中切换数据源_第9张图片
日志显示0,正常中。我们再次确认数据库。期望db1,db2都回滚,系列1问题就出在db2没有回滚。

Atomikos分布式事务中切换数据源_第10张图片
Atomikos分布式事务中切换数据源_第11张图片

正式搞定分布式事务。


总结:

不要放过任何小细节,时刻关注底层实现,了解原理。 好了,周末愉快! Atomikos分布式事务中切换数据源_第12张图片


你可能感兴趣的:(JAVA,分布式,源码解析,Spring)