我们的遗留应用程序使用JDBC 3.0。它通过实现自己的事务管理器来支持事务,该管理器能够为每个线程返回相同的JDBC连接。我最近发现的问题是它不支持嵌套事务:如果一个事务在另一个事务中启动,那么在内部事务上下文中运行的每个SQLs都将使用相同的db连接来执行,并且当它被提交或回滚时,它将自动提交或回滚从外部事务开始的所有更改。
据我所知,我可以使用JDBC 3.0保存点实现对嵌套事务的支持:每当启动嵌套事务时,我都可以为当前连接设置一个新的保存点。之后,如果回滚嵌套的事务,我将只回滚到这个保存点。另一方面,如果它被提交,我将什么也不做。只有最外层事务的提交才会保存对db的更改。
这是正确的吗?这种方法有什么缺陷吗?如果是,我的可能性是什么?
谢谢。
发布于 2009-02-06 12:51:52
代码中可能存在期望提交完成而不是延迟的依赖项(例如,如果隔离级别设置为TRANSACTION_READ_COMMITTED)。
考虑将事务管理器修复为在单独的连接上执行嵌套事务。
更新:看起来the Spring framework使用SavePoints来提供嵌套事务。我的猜测是他们只是忽略了隔离模式的问题。
发布于 2009-02-06 11:12:36
事务有点棘手,不能真正从JDBC层查看,而是从底层数据库本身查看。我将从现在开始谈论Oracle,因为它是我最有经验的东西。在Oracle中,如果启动一个事务,则可以回滚到事务中的保存点,但不能使用保存点进行提交。因此,假设我启动了一个事务,并且有三个保存点: A、B和C。我可以顺利地前进并回滚到A、B或C,但是一旦提交,您就已经启动了一个新事务,现在A、B和C不再有效。我希望这将有助于回答你的问题。
发布于 2009-06-02 12:44:27
您可以尝试Atomikos TransactionsEssentials中的嵌套事务支持。
但是,DBMS中的嵌套事务通常受到以下限制:
-either您的嵌套事务共享相同的DB事务,这允许以回滚粒度为代价进行共享数据访问(您回滚整个事务)
-or您的嵌套事务被映射(由Atomikos)到不同的底层DB事务,代价是不允许对热点数据进行共享数据访问
这种不匹配是由于数据库事务的ACID性质造成的。最终,您所有的DBMS访问都必然发生在这样的数据库事务中。
如果您想自己包装一些东西,您提到的保存点方法听起来很有希望-但是您可能需要确保对其进行广泛的测试。
最佳男主角
https://stackoverflow.com/questions/521669
复制相似问题