我有一个Spring / JDBC应用程序,它在很大程度上依赖于MySQL回滚进行单元测试。我发现如果我在这些事务中执行某些DDL操作 - 甚至在临时表上 - 即使在正常的DML语句上,回滚也会失败。例如:
@Test
@Rollback(true)
public void testRollbackProblem() {
template.update("create temporary table foo (id INTEGER )");
template.update("update forms set form_name = 'blah' where form_id = 1412");
template.update("alter table foo add (name text)");
}
此测试完成后,该中间语句将被保留并且不会回滚。有办法防止这种情况吗?也许某些参数传递给alter
语句?
答案 0 :(得分:2)
据我所知,这是MySQL的限制。 CREATE TABLE
和ALTER TABLE
语句导致隐式提交,无法回滚:
InnoDB中的CREATE TABLE语句作为单个事务处理。这意味着来自用户的ROLLBACK不会撤消用户在该事务期间所做的CREATE TABLE语句。
另见MySQL文档:https://dev.mysql.com/doc/refman/5.7/en/implicit-commit.html
<强>更新强>:
因为你正在使用CREATE TEMPORARY TABLE
它实际上不应该进行隐式提交,但是因为当你执行ALTER TABLE
时会发生这种情况:
如果使用TEMPORARY关键字,则CREATE TABLE和DROP TABLE语句不提交事务。 (这不适用于临时表上的其他操作,例如ALTER TABLE 和CREATE INDEX,它们会导致提交。)但是,虽然没有发生隐式提交,但是语句也不能回滚,意味着使用此类语句会导致违反事务原子性。例如,如果使用CREATE TEMPORARY TABLE然后回滚事务,则该表仍然存在。