【问题标题】:ERROR: extension "btree_gist" must be installed in schema "heroku_ext"错误:扩展“btree_gist”必须安装在模式“heroku_ext”中
【发布时间】:2022-08-19 16:30:07
【问题描述】:

Heroku 对 postgresql 的方式进行了更改extensions gets installed

这会在 heroku 中搞砸新的 Rails 审查应用程序,并出现以下错误。

错误:扩展“btree_gist”必须安装在模式“heroku_ext”中

这搞砸了,因为我需要删除现有的扩展并使用 heroku_ext 模式重新启用。我在运行迁移之前使用 bin/rails db:structure:load。

此外,随着 heroku 在审查应用程序中添加架构,struct.sql 也会发生变化,我们需要在本地开发机器中手动运行创建。

有人遇到过这个问题吗?

  • 不是 RoR,但这个问题也在讨论这个 Heroku PostgreSQL 变化:stackoverflow.com/questions/73206939/…
  • 你联系 Heroku 了吗?
  • 我们最近遇到了同样的问题。提交了支持票,但 Heroku 没有回应。
  • 我们确实联系了 heroku 并等待他们的回复。
  • 提交了工单,让我们的企业支持代表参与其中,他们的响应速度非常慢,而且没有详细信息。这正在影响我们的 BI 管道,我希望他们能提供一个选项来禁用数据库的这一新“功能”,直到他们解决这些问题。

标签: ruby-on-rails postgresql heroku heroku-postgres


【解决方案1】:

我开发了一个猴子补丁解决方案,这绝对是一个 hack,但比提前迁移或从 schema.rb 中删除行更好。

把它放在config/initializers。我打电话给我的_enable_extension_hack.rb 以确保它尽早加载。

module EnableExtensionHerokuMonkeypatch
  # Earl was here
  def self.apply_patch!
    adapter_const = begin
      Kernel.const_get('ActiveRecord::ConnectionAdapters::PostgreSQLAdapter')
    rescue NameError => ne
      puts "#{self.name} -- #{ne}"
    end

    if adapter_const
      patched_method = adapter_const.instance_method(:enable_extension)

      # Only patch this method if it's method signature matches what we're expecting
      if 1 == patched_method&.arity
        adapter_const.prepend InstanceMethods
      end
    end
  end

  module InstanceMethods
    def enable_extension(name)
      name_override = name

      if schema_exists?('heroku_ext')
        puts "enable_extension -- Adding SCHEMA heroku_ext"
        name_override = "#{name}\" SCHEMA heroku_ext -- Ignore trailing double quote"
      end

      super name_override
    end
  end
end

EnableExtensionHerokuMonkeypatch.apply_patch!

它有什么作用?它会对导致db/schema.rb 中的问题的enable_extension 调用进行猴子修补。具体来说,如果它发现有一个名为"heroku_ext"的模式,它会装饰enable_extension 的参数,以便执行的SQL 指定"heroku_ext" 模式。像这样:

CREATE EXTENSION IF NOT EXISTS "pg_stat_statements" SCHEMA heroku_ext -- Ignore trailing double quote"

如果没有这个 hack,生成的 SQL 看起来像这样:

CREATE EXTENSION IF NOT EXISTS "pg_stat_statements"

【讨论】:

  • 实际上是一个优雅的解决方案,可以避免更改迁移文件并防止需要在本地创建 heroku_ext 模式
  • 对于因ActiveRecord::ConnectionAdapters::PostgreSQLAdapter 名称错误而面临加载问题的任何人,您可以在补丁顶部添加一行:require "active_record/connection_adapters/postgresql_adapter"
【解决方案2】:

这是修补schema.rb 的更清洁方式

# config/initializers/patch_enable_extension.rb

require 'active_record/connection_adapters/postgresql_adapter'

# NOTE: patch for https://devcenter.heroku.com/changelog-items/2446
module EnableExtensionHerokuPatch
  def enable_extension(name, **)
    return super unless schema_exists?("heroku_ext")

    exec_query("CREATE EXTENSION IF NOT EXISTS \"#{name}\" SCHEMA heroku_ext").tap { reload_type_map }
  end
end

module ActiveRecord
  module ConnectionAdapters
    class PostgreSQLAdapter
      prepend EnableExtensionHerokuPatch
    end
  end
end

【讨论】:

  • 这是国际海事组织的正确答案。但是,我确实需要在顶部使用require 'active_record/connection_adapters/postgresql_adapter'
【解决方案3】:

编辑:这是官方更改日志作为参考https://devcenter.heroku.com/changelog-items/2446

由于最近的 Heroku 更改,您需要做一些不可想象的事情,并修改过去的迁移文件,以便您的审核应用程序与新的 Heroku 系统一起使用以进行扩展。

  1. 在第一个迁移文件connection.execute 'CREATE SCHEMA IF NOT EXISTS heroku_ext'的顶部添加一个predated,或
  2. 还可能将包含heroku_ext 的schema_search_path 添加到database.yml(如果您没有自定义,则将其设置为public,heroku_ext
  3. grep 全部enable_extension('extension_name')
  4. 将它们全部替换为connection.execute('CREATE EXTENSION IF NOT EXISTS "extension_name" WITH SCHEMA "heroku_ext")
  5. 祈祷足以解决问题

    进行这些更改后,我们仍然必须联系 heroku 支持,因为,为了:

    • pgaudit stack is not empty 错误
      • 这里的修复是运行两次维护(因为计划进行维护的 postgres 插件早于架构/扩展更改更改)
    • ERROR: function pg_stat_statements_reset(oid, oid, bigint) does not exist 错误
      • 这里的修复是 heroku 对数据库的手动干预。这是由于 heroku 试图在每次创建模式时运行 pg_stat_statements_reset 引起的。

【讨论】:

  • 对于现有数据库(例如在 prod 上),是否应该在 public 或 heroku_ext 中安装新的扩展?
  • @sguha 现有数据库中的所有新扩展都应在 heroku_ext 模式中创建。 (我添加了一个指向解释所有这些的 heroku 变更日志的链接)
  • 对于 4,我们应该使用“CREATE EXTENSION IF NOT EXISTS”,因为enable_extension 使用了该语句。
【解决方案4】:

这个黑客似乎对我有用。以下脚本在 app.json 中的部署后步骤中运行。

#!/bin/bash -xue
# Create extensions in the schema where Heroku requires them to be created
# The plpgsql extension has already been created before this script is run
heroku pg:psql -a $HEROKU_APP_NAME -c 'create extension if not exists citext schema heroku_ext'
heroku pg:psql -a $HEROKU_APP_NAME -c 'create extension if not exists pg_stat_statements schema heroku_ext'

# Remove enable_extension statements from schema.rb before loading it, since
# even 'create extension if not exists' fails when the schema is not heroku_ext
mv db/schema.rb{,.orig}
grep -v enable_extension db/schema.rb.orig > db/schema.rb
rails db:schema:load

【讨论】:

    【解决方案5】:

    截至 2022 年 8 月 16 日星期二,我们发现似乎不再需要补丁,enable_extension 似乎可以正常无缝运行,无需显式指定架构。

    当我在我们与 Heroku 支持的持续线程中提到这一点时,他们说他们围绕 heroku_ext 更改的一些修复可能在解决 https://status.heroku.com/incidents/2450 时已经发布,但仍有进一步的修复正在开发中,尚未发布被释放 - 所以我的猜测是这个特定问题是那些已经修复的问题!

    【讨论】:

    • 我今天尝试运行 pg:copy ,但我仍然遇到同样的问题
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-06-23
    • 1970-01-01
    • 2013-10-25
    • 1970-01-01
    • 2022-08-15
    • 2016-05-11
    • 1970-01-01
    相关资源
    最近更新 更多