错误:必须在架构"heroku_ext"中安装扩展"btree_gist"



Heroku对postgressql扩展安装的方式进行了更改

这导致heroku中新的rails评论应用程序出现以下错误。

错误:扩展名";btree_gist";必须安装在模式"中;herokuext";

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

此外,随着heroku在review应用程序中添加模式,structure.sql也会出现分歧,我们需要在本地开发机器中手动运行创建。

有人遇到这个问题吗?

我开发了一个猴子补丁解决方案,这绝对是一个黑客攻击,但比预先确定迁移日期或从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调用进行了monkey修补。具体来说,如果它发现有一个名为"heroku_ext"的模式,它将装饰enable_extension的参数,以便执行的SQL指定"heroku_ext"模式。像这样:

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

如果没有这个破解,生成的SQL看起来是这样的:

CREATE EXTENSION IF NOT EXISTS "pg_stat_statements"

这是修补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

EDIT:以下是官方的变更日志作为参考https://devcenter.heroku.com/changelog-items/2446

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

  1. 在第一个迁移文件connection.execute 'CREATE SCHEMA IF NOT EXISTS heroku_ext'的顶部添加一个previored
  2. 还可能向database.yml添加一个包含heroku_ext的schema_sasearch_path(如果您没有自定义,则将其设置为public,heroku_ext(
  3. 润滑所有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

这个破解似乎对我有效。以下脚本在app.json.中的postdeploy步骤中运行

#!/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

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

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

dzirtuss提供的答案让我大部分时间都在那里,为了让Rails应用程序正常工作,我必须做的最后一件事就是编辑config/database.yml中的搜索路径以包含heroku_ext。这是我添加到默认配置中的内容。

# config/database.yml
default:
schema_search_path: public,heroku_ext

在添加了初始化脚本和database.yml编辑之后,我能够成功地从一个应用程序运行heroku pg:copy,没有任何错误和意外行为。

Heroku最近引入了--extensions标志,这有助于解决问题。请参阅此常见问题解答。

例如,如果您使用的是btree_gist扩展,那么您可以在运行迁移之前使用heroku run pg:reset --extensions 'btree_gist' --app YOUR_APP_NAME,然后它们应该可以在不更改代码库的情况下工作。

  1. 使用Heroku数据存储持久性工具在源数据库或CCD_ 26
  2. 确定数据库使用的pg扩展(可以从psql中检查带\dx(
  3. 创建一个逗号分隔的扩展字符串(例如:fuzzystrmatch,pg_stat_statements,pg_trgm,pgcrypto,plpgsql,unaccent,uuid-ossp'(
  4. 确保您的Heroku CLI至少更新到7.63.0版本(使用heroku update更新(
  5. 运行此:
    heroku pg:backups:restore $(heroku pg:backups public-url -a <SOURCE_APP>) DATABASE_URL --extensions '<EXTENSIONS>' -a <TARGET_APP>
    
  6. 重置TARGET_APP上的dynos

相关内容

最新更新