ActiveRecord错误:SAVEPOINT active_record_1不存在

完整的错误是

ActiveRecord::StatementInvalid: Mysql2::Error: SAVEPOINT active_record_1 does not exist: ROLLBACK TO SAVEPOINT active_record_1 

每当我尝试创建一个新的ActiveRecord对象时,我正在编写unit testing并收到此错误 – 但仅在某个点之后。 这些行发生在以下行之后:

 ActiveRecord::Base.connection.execute "DROP TABLE IF EXISTS foo" ActiveRecord::Base.connection.execute "CREATE TABLE foo (id INTEGER PRIMARY KEY)" 

(如果我的测试成功,表’foo’将填充数据)

在上面这些行之前,我可以写一些类似的东西

 User.create(email => 'foo@bar.com') 

一切正常。 但是,如果我在调用ActiveRecord :: Base.connection.execute之后尝试编写上面的行,那么我得到上面描述的SAVEPOINT错误。 我也尝试将我的执行语句放在一个事务中,但这没有帮助。 我很难过。

仅供参考 – 我正在使用Rails 3.2.8

您正在使用Mysql DDE语句(create / drop / truncate table),这将导致隐式提交 。

由于隐式提交,将删除当前事务的所有保存点(请参阅上面的文档)。

要解决此问题,您可以关闭事务并使用DatabaseCleaner (截断模式)。

解决这个问题..

config.use_transactional_fixtures = false

创建/删除表时可以使用“TEMPORARY”。

http://dev.mysql.com/doc/refman/5.1/en/implicit-commit.html如果使用TEMPORARY关键字,则ALTER TABLE,CREATE TABLE和DROP TABLE不提交事务。 (这不适用于临时表上的其他操作,例如CREATE INDEX,它会导致提交。)但是,虽然没有发生隐式提交,但是语句都不能回滚。 因此,使用此类语句将违反事务primefaces性:例如,如果使用CREATE TEMPORARY TABLE然后回滚事务,则表仍然存在。

只是为了澄清。 您可以将触发MySql DDE语句的测试隔离到他们自己的文件中,然后在该文件中填写config.use_transactional_fixtures = false 。 这样,所有其他测试都不会受到影响。 现在,您负责在隔离的测试文件中进行清理。