【问题标题】:JDBC transaction rollback failure on closed connection关闭连接时 JDBC 事务回滚失败
【发布时间】:2015-02-11 12:54:35
【问题描述】:

如果在提交过程中与数据库资源的连接丢失,这可能导致提交失败然后回滚失败,事务是否可能部分提交?这似乎发生在我的案例中,但希望社区能更清楚地说明这一点。 HibernateTransactionManager 和 Oracle 正在与 JDBC 驱动程序一起使用。

【问题讨论】:

    标签: oracle hibernate jdbc transactions


    【解决方案1】:

    添加答案,因为我可以找到发生部分提交的原因。正在使用的 jdbc 连接池上设置了属性以删除废弃的连接。在从池中删除此类连接时,将对此类连接调用 close() ,这将导致提交当时正在使用这些连接的事务(从应用程序的角度来看不会被放弃)。一种解决方案是拦截此类关闭调用并回滚连接或适当处理

    【讨论】:

      【解决方案2】:

      否(除非 Oracle 中存在严重错误,或者除非我们谈论的是分布式事务)。

      如果客户端与数据库之间的连接丢失,则数据库可能从未收到提交事务的请求。在这种情况下,一旦数据库发现客户端死机(这可能需要一些时间),事务就会回滚。如果连接丢失,可能是数据库成功提交,但客户端始终没有收到提交成功的通知。

      如果我们谈论的是分布式事务,则事务可能在一个(或多个)分布式节点上仍然存在疑问。如果是这种情况,事务将出现在事务仍待处理的节点上的dba_2pc_pending 中。但它不会在任何节点上部分提交。

      如果我不得不猜测,如果您看到“部分提交”的内容,我敢打赌问题在于您的事务边界不正确,并且您在某处有一些正在提交的代码(隐含或明确)在您不期望的地方。

      【讨论】:

      • 我想我已经想通了,并且认为部分提交是可能的。 Oracle 在 connection.close 上发出隐式提交,因此在连接关闭之前的任何挂起提交都将提交,并且在连接关闭时无法处理的事务的挂起任务(由于 db 连接失败) 将被忽略。
      • @user2599052 - 如果您从代码中显式调用 connection.close,这意味着与数据库的连接不会丢失 - 您显然仍然可以调用close 方法。如果您有代码明确关闭连接,而其他步骤应该是事务的一部分,那不是“部分提交”,这是您的应用程序中的一个错误,导致您的事务边界不正确。
      • 我说的是在提交期间与数据库的连接丢失(不是由于应用程序代码)的场景。现在你认为“部分提交”是可能的吗?
      • @user2599052 - 否。如果与数据库的连接丢失,那么如果调用connection.close,客户端将发出commit 的事实是无关紧要的。届时将没有与数据库的连接来传输提交事务的请求。
      • 我同意 @Justin Cave 的 cmets,但也要考虑 Oracle 在执行 DDL 时隐式提交事务的事实。因此,如果您在事务中执行 DDL,也要考虑这一事实。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多