MySQL JDBC 回滚不成功。

4
我有一些Java代码,使用JDBC连接到MySQL数据库,然后进行一些读操作,再进行单个更新,所有操作都使用同一个连接。如果出现异常,则调用connection.rollback();如果没有异常,则调用connection.commit()。在这个阶段,每次运行我的测试时都会新创建一个连接(即它不来自池)。我的代码只创建了一个连接,并且在整个测试过程中都在使用它。
正在使用的连接在创建连接实例后立即调用了connection.setAutoCommit(false)
由于某种原因,当出现异常并调用connection.rollback()时,结果显示我的更新已经提交而不是回滚。
通过调试,我确认了以下内容:
  • 调用connection.setAutoCommit(false)后,connection.getAutoCommit()返回一个值false,如预期的那样。此外,"Select @@session.autocommit"返回一个值0,表示自动提交已关闭,如预期的那样。

  • 在调用connection.rollback()之前,相同的检查显示自动提交已关闭,如预期的那样。

  • connection.commit()明确未被调用,connection.rollback()明确被调用。

我还尝试了显式运行语句"rollback;",但它没有解决我的问题。我还尝试在创建连接后显式运行语句"Set AUTOCOMMIT = 0;"
我的所有表都使用InnoDB存储引擎。通过SQL Workbench,在自动提交关闭的情况下,回滚和提交按预期工作。
我正在使用MySQL版本“5.0.91-community-nt”。MySQL jdbc驱动程序版本为5.1.19。我正在使用Java 5。
有人有关于为什么我的更新即使自动提交关闭、从未调用提交并且明确调用回滚也被提交的建议吗?
谢谢。
1个回答

2
我在OP中提到的代码不是单个块,而是分散在各个类中。为了满足上述查询对代码示例的要求,我准备了一个单独的代码块来说明问题。一旦完成了代码块,我就测试它以确保我能够复制问题。然而,我无法复制该问题——回滚功能正常工作。这导致我查看生产代码,以确定所有超出我组合的代码块的事情。
结果发现,生产代码同时创建和删除临时表。最相关的是,在执行更新后,它会删除临时表,并且无论是否存在异常都会删除临时表。原来在MySQL中删除表会发出隐式提交调用。因此,在我的代码抛出异常并调用connection.rollback()之间,它会删除表,从而导致隐式调用提交。因此出现了“自动提交”问题。

请查看此链接(https://dev59.com/_nRB5IYBdhLWcg3wETxJ)。所有的DDL命令都会触发一个提交。 - richardtz
是的,但并非所有DDL都会导致提交。例如,我上面提到的临时表的创建不会导致隐式提交。我不确定不同的供应商是否会有所不同,但我现在已经找到了MySQL中导致隐式提交的DDL操作的明确列表。干杯。 - user1806029
@richardtz 这个问题涉及到Oracle。DDL的实际提交行为取决于数据库(这也是你拥有DatabaseMetaData.dataDefinitionCausesTransactionCommit()的原因之一)。 - Mark Rotteveel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接