使用JDBC 3.0实现对嵌套事务的支持

时间:2009-02-06 18:57:19

标签: java jdbc transactions

我们的遗留应用程序使用JDBC 3.0。它通过实现自己的事务管理器来支持事务,该事务管理器能够为每个线程返回相同的JDBC连接。我最近发现的问题是它不支持嵌套事务:如果事务是在另一个事务中启动的,那么在内部事务的上下文中运行的每个SQL都将使用相同的数据库连接执行,并且当它被提交或者回滚它会自动提交或回滚从外部事务开始的所有更改。

据我所知,我可以使用JDBC 3.0保存点实现对嵌套事务的支持:每当启动嵌套事务时,我都可以为当前连接设置新的保存点。之后,如果回滚嵌套事务,我将回滚到此保存点。另一方面,如果它被提交,我将什么都不做。只有最外部事务的提交才会将更改保存到db。

这是对的吗?这种方法有缺陷吗?如果是的话,我的可能性是什么?

感谢。

3 个答案:

答案 0 :(得分:1)

事务有点棘手,无法真正从JDBC层查看,而是从底层数据库本身查看。我将从这里谈论Oracle,因为这是我最有经验的。在Oracle中,如果启动事务,则可以回滚到事务中的保存点,但不能使用保存点提交。所以假设我开始一个事务并有三个保存点,A,B和C.我可以愉快地前进并回滚到A,B或C,但是一旦你提交,你就开始了一个新的事务,现在是A,B ,和C不再有效。我希望这有助于回答你的问题。

答案 1 :(得分:1)

代码中可能存在依赖于期望提交而不是延迟的依赖(例如,如果隔离级别设置为TRANSACTION_READ_COMMITTED)。

考虑修复您的事务管理器以在单独的连接上执行嵌套事务。

更新:看起来the Spring framework使用SavePoints来提供嵌套事务。我猜他们只是忽略了隔离模式的问题。

答案 2 :(得分:1)

您可以尝试Atomikos TransactionsEssentials中的嵌套事务支持。

但是,DBMS中的嵌套事务通常以下列方式受到限制:

- 您的嵌套事务共享相同的数据库事务,这允许以回滚粒度为代价进行共享数据访问(您回滚整个事务)

- 或者您的嵌套事务(由Atomikos)映射到不同的底层数据库事务,代价是不允许对热点数据进行共享数据访问

这种不匹配是由于数据库事务的ACID性质造成的。最终,所有DBMS访问都必然会发生在这样的数据库事务中。

如果你想自己包装一些东西,你提到的保存点方法看起来很有希望 - 但是你可能需要确保广泛测试它。

最佳