首先,这个问题不是关于应用外部XA事务管理器的,因为这肯定会解决问题。问题是如果没有以下假设,该如何解决:
现在让我们假设以下情况:
以我的感觉,一切都需要“嵌套事务”解决方案,幸运的是,Spring DataSourceTransactionManager
支持此解决方案。问题是,Propagation.NESTED
假定事务X和Y都在同一数据库(DataSource
)中执行,并且可能在同一基础JDBC Connection
上执行。但这显然不是我的情况,因为数据库具有单独的连接并能够支持独立的事务。
我尝试的另一种可能的解决方案是创建两个DataSourceTransactionManager
实例,每个数据库一个。乍一看,它看起来是一个更干净的解决方案-但后来我意识到标准的Spring类在很大程度上依赖于静态的线程局部字段,从而确保了在尝试通过同一线程同时使用两个管理器时彼此重担(请参见上面的假设) )。不行。
现在,我正在考虑对所有相关的Spring事务管理类进行子类化,以“分离”程序包之间的那些共享静态字段。不过,感觉就像是发明了一辆自行车,所以我宁愿不这样做。
由于外部XA事务管理器被认为是过大的(由于一致性要求非常宽松,请参见上文),因此它是唯一落在JDBC级别并以编程方式管理事务Y(开始,读取,写入数据,提交)的解决方案?还是我错过了spring-tx
中的一些高级概念?
答案 0 :(得分:0)
我不是Spring专家(因此我无法对子类化的概念说什么),但是我知道Spring事务使用JTA的能力。
正如您所说,DataSourceTransactionManager
仅针对每个资源工作,并且NESTED
功能是可能的,这是因为JDBC API及其与安全点(https://docs.oracle.com/javase/8/docs/api/java/sql/Connection.html#setSavepoint--)一起工作的功能。此功能仅限于一个Connection
。
我认为您可以按照建议进行手动JDBC管理。还是我仍然考虑交易经理。事务管理器不仅管理XA事务,而且还提供JTA api的实现,您可以使用声明性或编程方法。事务管理的最大开销是XA处理-在应用程序和数据库端的准备过程中,数据需要保存到驱动器中。如果仅将事务管理功能与非XA资源一起使用,则事务管理器会为您提供JTA api来运行事务,不提供一致性(这不是您所需要的),并且不使用XA开销。
如果您使用事务管理器和两个非XA资源(DriverManagerDataSource
),则可以驱动如下事务-开始-更新数据-暂挂#1-开始-更新数据-提交#2-恢复#1-提交。
不幸的是,您的特殊情况最适合JTA不支持的嵌套事务模型。
但是即使使用NESTED
Spring范围,这种情况也正是您所需要的。嵌套的工作方式是,如果嵌套事务被回滚,则外部事务不会自动回滚。换句话说,嵌套事务(事务Y
)的回滚并不意味着外部事务也被回滚(事务X
)。