执行rake db:structure:load或rake db:setup时Heroku Postgres扩展报错如何解决?
rake db:structure:load时的plpgsql权限错误 Hey there, let's fix that annoying plpgsql permission error you're getting when running rake db:structure:load on Heroku. Here's what's going on and how to resolve it:
问题根源
Heroku Postgres的应用数据库用户没有超级用户权限,而你的db/structure.sql里大概率包含了和plpgsql扩展相关的语句(比如CREATE EXTENSION IF NOT EXISTS plpgsql;)。但实际上,plpgsql是Heroku Postgres默认就启用的扩展,而且它的所有权属于Heroku的超级用户,你的应用用户根本没权限修改它,所以执行加载命令时就会触发这个权限错误。
解决方案
1. 永久解决:配置Rails自动排除plpgsql的dump
每次执行rake db:structure:dump时,Rails默认会把所有已安装的扩展都写到structure.sql里。我们可以让它跳过plpgsql:
打开config/application.rb,添加以下配置(根据你的Rails版本选择合适的方式):
对于Rails 6+:
config.active_record.schema_dump_extensions = lambda do |extension| extension.name != 'plpgsql' end对于旧版本Rails:
config.active_record.schema_dump_extensions = []
添加后,下次执行rake db:structure:dump生成的structure.sql就不会包含plpgsql相关语句了,提交修改后重新部署到Heroku,再执行heroku run rake db:structure:load就不会报错了。
2. 临时解决:手动修改structure.sql
如果不想修改配置,你可以手动处理structure.sql:
- 本地执行
rake db:structure:dump生成最新的结构文件 - 打开
db/structure.sql,删除所有包含plpgsql的行(比如CREATE EXTENSION IF NOT EXISTS plpgsql;或者COMMENT ON EXTENSION plpgsql IS ...) - 提交修改后的structure.sql到代码库,重新部署到Heroku,再执行加载命令即可。
3. 应急方案:执行命令时过滤plpgsql语句
如果不想重新部署,也可以在执行load命令时临时过滤掉plpgsql相关行:
heroku run "psql -v ON_ERROR_STOP=1 -q -f <(sed '/plpgsql/d' /app/db/structure.sql) d7u1inlf2d16bd" -a my_heroku_app
不过这个方法只是临时救急,下次部署新的structure.sql后还是会遇到同样的问题,所以优先推荐前两种方案。
内容的提问来源于stack exchange,提问作者Julie

