每当我们部署 Rails/Postgres 应用程序并且迁移是部署的一部分时,我们都会收到以下错误:
PG::InFailedSqlTransaction: ERROR: current transaction is aborted, commands ignored until end of transaction block
PG::FeatureNotSupported: ERROR: cached plan must not change result type
有问题的 SQL 事务通常是不同的。
我想知道是否有办法在我们部署时防止这种情况发生?
最佳答案
原因:
兑现准备好的报表是为了提高性能。 每当在更改相关表的架构后使用准备好的语句时,您将得到:
PG::FeatureNotSupported: ERROR: cached plan must not change result type
PG 的适配器通常可以通过 DEALLOCATE
正常恢复。正在准备的声明。
但是,如果错误发生在事务中,则事务已经失败。 DEALLOCATE
语句在同一事务内运行,因此会回滚。
因此,连接留下了一个不起作用的兑现准备好的报表。
解决方案:
- 问题解决后升级到 Rails 5.0.4+ there .
- 运行迁移时不要运行任何 Rails 进程。如果您希望零停机部署,则不适用。适用,但如果您有多个应用程序访问同一数据库,则不方便。
Disable prepared statements共。可能会也可能不会导致性能下降:
# config/database.yml production: prepared_statements: false
添加following monkey patch到
ActiveRecord::Base
(略有修改的版本):# config/initializers/rails_recoverable_transactions.rb raise "Remove monkey patch in #{__FILE__}" if Rails::VERSION::MAJOR > 4 module TransactionRecoverable module ClassMethods def transaction(*args) super(*args) do yield end rescue PG::InFailedSqlTransaction connection.rollback_db_transaction connection.clear_cache! super(*args) do yield end end end end class << ActiveRecord::Base prepend TransactionRecoverable::ClassMethods end
这可以确保,如果您在事务中遇到上述错误,则首先关闭事务,然后清除缓存,然后重试事务一次。如果由于某种原因您不想重试交易,您可以删除 rescue
block 内的 super
调用。
关于postgresql - 将rails应用程序部署到heroku时经常看到PG::InFailedSqlTransaction错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37217661/