我有一个应用程序 - 更像是一个实用程序 - 位于角落并定期更新两个不同的数据库.
它是一个使用Spring Application Context构建的小型独立应用程序.上下文中配置了两个Hibernate会话工厂,依次使用Spring中配置的Commons DBCP数据源.
目前没有交易管理,但我想补充一些.对一个数据库的更新取决于对另一个数据库的成功更新.
该应用程序不在Java EE容器中 - 它由从shell脚本调用的静态启动程序类引导.启动器类实例化Application Context,然后在其中一个bean上调用方法.
围绕数据库更新放置事务性的"最佳"方法是什么?
我将"最好"的定义留给您,但我认为它应该是"易于设置","易于配置","便宜"和"易于打包和重新分发"的功能.自然FOSS会很好.
在多个数据库上分发事务的最佳方法是:不要.
有些人会指向XA,但XA(或两阶段提交)是谎言(或市场营销).
想象一下:在第一阶段告诉XA经理它可以发送最终提交之后,与其中一个数据库的网络连接失败.怎么办?超时?这会让其他数据库损坏.回滚?两个问题:你无法回滚提交,你怎么知道第二个数据库发生了什么?成功提交数据后,网络连接可能失败,只有"成功"消息丢失了?
最好的方法是将数据复制到一个地方.使用允许您中止副本并随时继续使用的方案(例如,忽略您已有的数据或按ID排序选择并仅请求副本的记录> MAX(ID)).通过交易保护这一点.这不是问题,因为您只是从源读取数据,因此当事务因任何原因失败时,您可以忽略源数据库.因此,这是一个简单的旧单源事务.
复制数据后,在本地处理它.
在您的上下文中设置事务管理器.Spring文档有例子,而且非常简单.然后当你想要执行一个事务时:
try { TransactionTemplate tt = new TransactionTemplate(txManager); tt.execute(new TransactionCallbackWithoutResult(){ protected void doInTransactionWithoutResult( TransactionStatus status) { updateDb1(); updateDb2(); } } catch (TransactionException ex) { // handle }
有关更多示例,请参阅此信息: 使用Spring的XA事务
当您说"两个不同的数据库"时,您是指不同的数据库服务器,还是同一个数据库服务器中的两个不同的模式?
如果是前者,那么如果你想要完全的事务性,那么你需要XA事务API,它提供完整的两阶段提交.但更重要的是,您还需要一个事务协调器/监视器来管理不同数据库系统之间的事务传播.这是JavaEE规范的一部分,也是其中非常罕见的一部分.TX协调器本身就是一个复杂的软件.您的应用程序软件(通过Spring,如果您愿意)与协调员交谈.
但是,如果您只是指同一个数据库服务器中的两个数据库,那么vanilla JDBC事务应该可以正常工作,只需在单个事务中对两个数据库执行操作.