Ruby on rails ActiveRecord::语句无效:PG InFailedSqlTransaction

Ruby on rails ActiveRecord::语句无效:PG InFailedSqlTransaction,ruby-on-rails,postgresql,activerecord,rollback,pg,Ruby On Rails,Postgresql,Activerecord,Rollback,Pg,我正在尝试创建一个ActiveRecord对象,但在创建它时出现了此错误 (0.1ms) ROLLBACK ActiveRecord::StatementInvalid: PG::InFailedSqlTransaction: ERROR: current transaction is aborted, commands ignored until end of transaction block 大家对这个问题有什么看法。我有这个问题。只要重新启动Rails服务器,它就应该可

我正在尝试创建一个ActiveRecord对象,但在创建它时出现了此错误

(0.1ms)  ROLLBACK
ActiveRecord::StatementInvalid: PG::InFailedSqlTransaction: ERROR:  current transaction is       aborted, commands ignored until end of transaction block

大家对这个问题有什么看法。

我有这个问题。只要重新启动Rails服务器,它就应该可以工作了

这个问题发生在我的测试环境中,是因为每个测试都被包装在自己的事务中

我使用的是数据库_cleanergem,并对其进行了配置,以便在使用javascript时不会将测试包装到事务中。所以为了解决这个问题,我在每个导致这个问题的规范中添加了
js:true
。(尽管规范实际上没有使用javascript,但这是确保测试不会被封装在事务中的最方便的方法。不过,我相信有更少的黑客方法可以做到这一点)

以下是
spec/support/database\u cleaner.rb
中的数据库\u cleaner配置,仅供参考:

RSpec.configure do |config|

  config.before(:suite) do
    DatabaseCleaner.clean_with :deletion
  end

  config.before(:each) do
    DatabaseCleaner.strategy = :transaction
  end

  config.before(:each, :js => true) do
    DatabaseCleaner.strategy = :deletion
  end

  config.before(:each) do
    DatabaseCleaner.start
  end

  config.after(:each) do
    DatabaseCleaner.clean
  end

end

如果您没有使用database_cleaner,那么将测试包装在事务中的原因可能是
use_transactional_fixtures
选项在
spec/spec\u helper.rb
中设置为
true
。尝试将其设置为false。

你可以在postgresql日志中看到真正发生的情况,我花了很多时间深入研究这个问题,最终发现我们误用upsert gem导致PG错误,只有在postgresql日志中才有真正的信息


我在引用规范中不再存在的列时遇到此错误。确保您的数据库是最新的,并且您的代码不希望出现不存在的列。

其他答案都无法解决问题的根本原因

问题是,当Postgres引发异常时,它会毒害同一连接上的未来事务

解决方法是回滚有问题的事务:

begin
  ActiveRecord...do something...
rescue Exception => e
  puts "SQL error in #{ __method__ }"
  ActiveRecord::Base.connection.execute 'ROLLBACK'

  raise e
end

请参阅。

在将Rails从4.2.2升级到4.2.5后出现类似问题,我必须升级
pg
gem,问题开始出现

9) WorkPolicy#is_publicly_viewable? is publicly visible hides work if deleted
     Failure/Error: before { DatabaseCleaner.clean_with :deletion }
     ActiveRecord::StatementInvalid:
       PG::InFailedSqlTransaction: ERROR:  current transaction is aborted, commands ignored until end of transaction block
       :             SELECT tablename
                   FROM pg_tables
                   WHERE schemaname = ANY (current_schemas(false))
从这个意义上讲,这是正确的,只是总结一下问题:

有时,当您将
DatabaseCleaner.clean_与:deletion一起使用时,可能会干扰PostgreSQL事务

因此,我的解决方案是在部分测试中将
DatabaseCleaner.clean_替换为:deletion
,而这是由
DatabaseCleaner.clean_导致的,使用:truncation

对谷歌用户来说,还有一件事。如果您注意到此堆栈跟踪:

An error occurred in an `after(:context)` hook.
ActiveRecord::StatementInvalid: PG::UndefinedColumn: ERROR:  column "table_rows" does not exist
LINE 1: ...ion_schema.tables WHERE table_schema = 'test' AND table_rows...
^
…这可能是由此问题引起的

问题:

  • 程序执行错误的SQL语句。错误的SQL语句是问题的根本原因
  • 在错误的SQL语句之后,程序不会立即回滚或释放保存点
  • 程序在错误的SQL语句之后执行SQL语句
  • PostgreSQL引发错误:当前事务被中止,在事务块结束之前忽略命令
  • 解决方案:

    查找不正确的SQL语句并更正它。
    如果不想更正SQL语句,请在不正确的SQL语句后使用回滚或释放保存点。

    在我的例子中,我收到此错误只是因为我没有rake我的测试数据库

    在我的例子中,位于
    /usr/local/var/Postgres/postgresql.conf
    的Postgres配置的日期类型是国际格式的
    dmy

    将日期类型更改为美国格式的
    mdy
    为我解决了这个问题。

    我遇到了这个问题。 我发现这是我的疑问。 这意味着当我在不指定表列的情况下使用关联进行查询时。 例:


    如果您禁用事务性装置而不插入DatabaseCleaner之类的东西,那么您的测试数据库将继续累积每次运行的数据。您可以为集成规范设置它,而不是为每个不按预期工作的规范设置
    js:true
    。请记住,使用
    :deletation
    而不是
    :transaction
    的速度要慢得多,因此在可行的情况下,最好使用事务。在这一点上,我发现与默认事务测试相比,DB Cleaner增加的复杂性非常困难(也就是出现更多错误)。但我的问题是,在同一个
    it
    块中有两个请求,如
    get…
    。将其移出修复了此错误。我不认为添加
    js:true
    是修复此问题的最佳方法。它不能解决问题,而且删除策略非常缓慢。通过切换到事务策略,我将测试速度提高了2.5倍。请看下面我的答案。事实上,我刚刚遇到了这个问题,重新启动服务器确实解决了它。有人对这种行为有解释吗?我在测试环境中也有同样的问题(rspec抛出错误)
    rakedb:drop
    +
    rakedb:create
    +
    rakedb:migrate
    解决了这个问题。也许我把迁移搞砸了。我在rails控制台中测试。重新加载不足,需要重新启动控制台。谢谢这不是一个可行的解决方案,当服务应该自动运行时,重新启动服务器不是一个选项。问题是PG连接处于错误状态,需要重新连接,或者需要执行
    回滚
    以退出当前事务。这在升级到PG12和Ruby 2.6.6后发生。我使用rvm,升级到2.6.6需要为新的gemset重建pg gem。一个
    rakedb:test:prepare
    不起作用,但是一个
    rakedb:drop db:create db:migrate
    解决了这个问题。这个链接没有什么帮助,但是检查postgres日志的想法完全起作用了。在我的例子中,它是一个未准备好的测试数据库。谢谢Rails中也提到了请不要从
    异常中解救,正如这里所说的:异常是Ruby异常层次结构的根,所以当你解救异常时,你会从一切中解救出来,包括子类,如SyntaxError、LoadError和Int
    
    class Holiday < ApplicationRecord
         belongs_to :company
    end
    
    class Company < ApplicationRecord
        has_many :timeoffs
    end
    
    company.timeoffs.where("(start_date <= ? and end_date >= ?) and id != ?", begin_date, begin_date, 1)
    
    company.timeoffs.where("(start_date <= ? and end_date >= ?) and time_offs.id != ?", begin_date, begin_date, 1)