ActiveRecord :: StatementInvalid:PG InFailedSqlTransaction


72

我正在尝试创建一个ActiveRecord Object。但是在创建它时遇到了这个错误。

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

关于这个问题的任何想法。


您正在使用列类型为PSQL的PSQLjson吗?将其更新为PSQL 9.4并使用jsonb。问题解决了!
胚芽

postgresql.org/docs/9.1/static/transaction-iso.html这是我们遇到的主要问题。
解开了

Answers:


108

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

问题是,当Postgres引发异常时,它会使同一连接上的将来交易中毒。

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

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

  raise e
end

参见参考



12
请不要从Exception这里救援,如此处所述:stackoverflow.com/questions/10048173/…Exception 是Ruby异常层次结构的根,因此,当您救援Exception时,您会从所有内容中进行救援,包括SyntaxError,LoadError和Interrupt等子类。
adantj

1
在我粘贴该链接的评论中,它清楚地说明了您的代码有问题且部分错误的建议的原因。该链接还提供其他信息。您的“为什么不呢?” 注释没有意义,除非您没有阅读注释,链接或两者都没有。如果您不花时间考虑您的问题和答案,那我还要问同样的事情,那为什么还要发布它们呢?
adantj

2
@adantj当您立即重新筹集筹码时,可以拯救Exception ;就像给定的答案一样
桑普森·克劳利

1
像魅力一样工作,非常感谢!
Andreas Gebhard

84

我有这个问题。只需重新启动Rails Server,它应该可以工作


7
实际上,我只是遇到了这个问题,重新启动服务器确实解决了该问题。有人对此行为有解释吗?
2014年

1
我在测试环境上遇到了相同的问题(rspec引发错误)。rake db:drop+ rake db:create+rake db:migrate解决了这个问题。也许我搞砸了迁移。
Nobu 2015年

在Rails控制台中进行测试。重新加载不足,需要重新启动控制台。谢谢!
Volte 2015年

这不是一个可行的解决方案,当服务应该自动运行时,重启服务器是不可行的。问题是PG连接处于错误状态,需要重新连接或需要执行ROLLBACK才能退出当前事务。
thesmart

升级到PG12和Ruby 2.6.6之后,这发生在我身上。我使用rvm,升级到2.6.6需要为新的宝石集重建pg宝石。Arake db:test:prepare没有用-但是RAILS_ENV=test rake db:drop db:create db:migrate解决了问题。
Martin Streicher

15

此问题是在我的测试环境中发生的,并且是由于每个测试都包装在自己的事务中这一事实引起的。

我使用的是database_cleaner gem,并对其进行了配置,以便如果测试使用JavaScript,则不将测试包装在事务中。因此,为了解决该问题,我将js: true每个导致此问题的规范添加到了其中。(即使以为规范并未真正使用javascript,这也是确保测试不会被封装在事务中的最便捷方法。不过,我敢肯定,这样做的方式不多。

作为参考,这是来自的database_cleaner配置spec/support/database_cleaner.rb

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选项设置为truein spec/spec_helper.rb。尝试将其设置为false。


如果禁用事务固定装置而不插入诸如DatabaseCleaner之类的东西,那么您的测试数据库将继续在每次运行中堆积数据。js: true您可以为集成规范设置它,而不是为每个不能按预期运行的规范设置。请记住,使用:deletion而不是使用:transaction速度要慢得多,因此在可行的情况下最好进行事务处理。
lobati 2014年

到目前为止,我发现与默认的事务测试相反,数据库清理程序增加了复杂性(又弹出了更多错误)。但是我的问题是我有两个请求,就像get ...在同it一块中一样。将其移出可解决此错误。
瑞安

我认为添加不是js: true解决此问题的最佳方法。它不能解决问题,删除策略非常慢。通过切换到交易策略,我的测试速度提高了2.5倍。请参阅下面的答案。
B 2015年

8

您可以看到postgresql日志中真正发生的事情,我花了很多时间来研究这个问题,最后发现我们滥用了upsert gem导致PG错误,只有在postgresql日志中才有正在发生的事情的真实信息。

https://github.com/seamusabshere/upsert/issues/39


1
链接并没有多大帮助,但是完全检查postgres日志的想法确实有用。就我而言,这是一个未经准备的测试数据库。谢谢!
Mat Schaffer

6

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


3

问题:

  1. 程序执行了不正确的SQL语句。错误的SQL语句是问题的根本原因。
  2. 错误的SQL语句后,程序不会立即ROLLBACK或RELEASE SAVEPOINT。
  3. 程序在错误的SQL语句之后执行SQL语句。
  4. PostgreSQL引发错误:当前事务中止,命令被忽略,直到事务块结束

解:

查找不正确的SQL语句并更正它。如果您不想更正SQL语句,请在错误的SQL语句之后使用ROLLBACK或RELEASE SAVEPOINT。


2

就我而言,我收到此错误的原因仅仅是因为我没有耙我的测试数据库。


2

就我而言,Postgres配置位于 /usr/local/var/postgres/postgresql.conf的datetype为以下格式的国际格式dmy

将datetype更改为美国格式可以mdy为我解决此问题。


0

在将Rails从4.2.2升级到4.2.5后出现了类似的问题,我不得不升级pggem并开始发生问题

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_with :deletion时可能会干扰PostgreSQL事务。

所以对我来说解决方案是更换 DatabaseCleaner.clean_with :deletion部分测试导致的DatabaseCleaner.clean_with :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...
^

...可能是这个问题引起的


0

我有那个问题。我发现这是我的查询。这意味着当我使用关联查询而不指定表列时。例如:

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)

发生错误是因为我没有指定将哪个表id 更改为

company.timeoffs.where("(start_date <= ? and end_date >= ?) and time_offs.id != ?", begin_date, begin_date, 1)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.