2012-11-07 45 views
4

我有一些Java代码使用JDBC连接到MySQL数据库,然后代码执行一些读取操作,然后进行单个更新,所有更新都使用相同的连接。如果有例外,则调用connection.rollback();如果没有例外,则调用connection.commit()。在这个阶段,每次运行我的测试时都会新建连接(即它不是来自池)。我的代码只创建一个连接,并在整个测试中使用。mysql jdbc不成功回滚

正在使用的连接在创建连接实例后立即调用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

有没有人有任何建议,为什么我的更新是越来越致力于即使自动提交关闭时,提交不会被调用,并回滚显式调用?

干杯。

+2

请张贴代码,你试过。 – sunleo

+0

代码请!!!!! – Konza

回答

2

我在OP中引用的代码不在一个块中,它分散在不同的类中。为了满足上述关于代码示例的查询,我准备了一段代码来解决问题。一旦代码块完成,我测试它以确保我可以复制该问题。那么,我无法复制这个问题 - 回滚工作得很好。这导致我通过生产代码来计算出它在我放在一起的代码块之外所做的所有事情。

事实证明,生产代码都创建和删除临时表。最相关的是,它在执行更新后删除临时表,并删除临时表,无论是否存在异常。事实证明,在MySQL中删除一个表会发出隐式的提交调用。因此,在我的代码抛出一个异常和我的代码调用connection.rollback()之间,它会抛出导致隐式调用提交的表。因此我的'自动提交'问题。

+0

检查这一个(http://stackoverflow.com/questions/730621/do-ddl-statements-always-give-you-an-implicit-commit-or-can-you-get-an-implicit)。所有DDL命令执行提交。 – richardtz

+0

是的,但不是所有的DDL都会导致提交。例如,上面提到的创建临时表不会导致隐式提交。我不确定是否有不同的供应商对彼此做了不同的处理,但我现在已经找到了导致MySQL中隐式提交的DDL操作的权威列表。干杯。 – user1806029

+0

@richardtz这个问题涉及Oracle。 DDL的实际提交行为依赖于数据库(您有[DatabaseMetaData.dataDefinitionCausesTransactionCommit()']的原因之一(http://docs.oracle.com/javase/7/docs/api/java/sql/DatabaseMetaData。 HTML#dataDefinitionCausesTransactionCommit())。 –