25

完整的错误是

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

每当我尝试创建一个新的 ActiveRecord 对象时,我正在编写一个单元测试并得到这个错误——但只有在某个点之后。这发生在这些行之后:

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 error上述内容。我也尝试将我的执行语句放在事务中,但这没有帮助。我难住了。

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

4

6 回答 6

27

您正在使用 Mysql DDE 语句(创建/删除/截断表),这将导致隐式提交

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

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

于 2012-12-05T20:52:33.443 回答
6

为了解决这个问题。。

config.use_transactional_fixtures = false

于 2013-06-13T06:14:04.903 回答
3

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

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

于 2013-03-28T21:02:27.863 回答
2

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

于 2014-04-03T16:28:04.973 回答
0

I found the following links that helped me:

于 2012-11-06T08:00:28.790 回答
0

首先确保您安装了 DatabaseCleaner gem,这将允许您选择数据库清理策略。我们收到的错误意味着最好使用该truncation策略。

# file: Gemfile

group :test do
  gem ‘database_cleaner’
end

将 DatabaseCleaner 配置添加到 features 目录(见下文)。

#file: features/support/database_cleaner.rb

begin
  require 'database_cleaner'
  require 'database_cleaner/cucumber'

  DatabaseCleaner.strategy = :truncation
rescue NameError
  raise "You need to add database_cleaner to your Gemfile (in the :test group) if you wish to use it."
end

Around do |scenario, block|
  DatabaseCleaner.cleaning(&block)
end
于 2019-01-30T09:51:09.440 回答