恢复PostgreSQL数据库时如何解决特权问题


104

我使用以下命令为Postgres数据库转储了干净的没有所有者的备份

pg_dump sample_database -O -c -U

稍后,当我使用

psql -d sample_database -U app_name

但是,我遇到了几个错误,这些错误使我无法还原数据:

ERROR:  must be owner of extension plpgsql
ERROR:  must be owner of schema public
ERROR:  schema "public" already exists
ERROR:  must be owner of schema public
CREATE EXTENSION
ERROR:  must be owner of extension plpgsql

我深入研究了纯文本SQL pg_dump生成,发现其中包含SQL

CREATE SCHEMA public;
COMMENT ON SCHEMA public IS 'standard public schema';
CREATE EXTENSION IF NOT EXISTS plpgsql WITH SCHEMA pg_catalog;
COMMENT ON EXTENSION plpgsql IS 'PL/pgSQL procedural language';

我认为原因是用户app_name没有更改public架构和的权限plpgsql

我该如何解决这个问题?


5
如果您不需要plpgsql,那么DROP EXTENSION plpgsql在您之前pg_dump。这比使您的应用成为超级用户更安全,并且比忽略错误(如果使用--single-transaction或会炸弹)更方便-v ON_ERROR_STOP=1。这是一个已知问题,[由Postgres开发人员详细讨论| postgresql.org/message-id/…,但自9.3起未修复。
Mark E. Haase

Answers:


63

要解决此问题,您必须分配适当的所有权权限。请尝试以下方法,该方法可以解决特定用户的所有权限相关问题,但如注释中所述,不应在生产环境中使用:

root@server:/var/log/postgresql# sudo -u postgres psql
psql (8.4.4)
Type "help" for help.

postgres=# \du
               List of roles
    Role name    | Attributes  | Member of
-----------------+-------------+-----------
 <user-name>    | Superuser   | {}
                 : Create DB
 postgres       | Superuser   | {}
                 : Create role
                 : Create DB

postgres=# alter role <user-name> superuser;
ALTER ROLE
postgres=#

因此,以超级用户帐户连接到数据库sudo -u postgres psql并执行一条ALTER ROLE <user-name> Superuser;语句。

请记住,这不是多站点托管服务器上的最佳解决方案,因此请看看分配各个角色:https : //www.postgresql.org/docs/current/static/sql-set-role.htmlhttps ://www.postgresql.org/docs/current/static/sql-alterrole.html


28
有没有办法不用超级用户就能做到这一点?
特拉维斯·韦伯

17
“必须分配适当的所有权权限”和“更改角色<用户名>超级用户”不是一致的。正确的所有权将意味着app_user不是超级用户。
Mark E. Haase 2015年

@mehaase,请更新答案的措词,而不要投反对票。
Daniel Sokolowski

5
恕我直言,这不是解决方案,而是在生产中应避免的解决方法。
Dmytriy Voloshyn 2015年

6
成为普通用户是个坏建议superuser
Evren Yurtesen

55

AWS RDS用户(如果要获得此权限)是因为您不是超级用户,并且根据aws文档,您不能成为超级用户。我发现我必须忽略这些错误。


5
此错误正在阻止我完成还原(AWS RDS pg_restore)。有任何忽略这些错误的提示吗?
avjaarsveld'3

PS我没有对pg_restore使用-e或--exit-on-error
avjaarsveld'Mar

6
我发现在RDS上,问题COMMENT ON EXTENSION不是CREATE EXTENSION。删除评论,就可以了。
pkoch

@pkoch与Google Cloud Storage相同。关于扩展的评论是问题,而不是必需的
Jaybeecave

25

对于使用Google Cloud Platform的用户,任何错误都会停止导入过程。我个人遇到了两个不同的错误,具体取决于我发出的pg_dump命令:

1- The input is a PostgreSQL custom-format dump. Use the pg_restore command-line client to restore this dump to a database.

尝试以非纯文本格式转储数据库时发生。即当命令缺少-Fp或--format = plain参数时。但是,如果将其添加到命令中,则可能会遇到以下错误:

2 SET SET SET SET SET SET CREATE EXTENSION ERROR: must be owner of extension plpgsql

这是一个权限问题,我无法使用GCP文档中提供的命令,该当前线程的提示或遵循Google Postgres团队的建议(在此处)进行修复。建议哪个发出以下命令:

pg_dump -Fp --no-acl --no-owner -U myusername myDBName > mydump.sql

在我看来,唯一能够解决问题的方法是手动编辑转储文件并注释掉与plpgsql相关的所有命令。

我希望这对GCP依赖的灵魂有所帮助。

更新:

转储注释扩展名的文件更容易,尤其是因为某些转储可能非常庞大: pg_dump ... | grep -v -E '(CREATE\ EXTENSION|COMMENT\ ON)' > mydump.sql

可以缩小到plpgsql: pg_dump ... | grep -v -E '(CREATE\ EXTENSION\ IF\ NOT\ EXISTS\ plpgsql|COMMENT\ ON\ EXTENSION\ plpgsql)' > mydump.sql


1
GCP现在pg_dump可以在其文档中使用确切的命令了:pg_dump -U [USERNAME] --format=plain --no-owner --no-acl [DATABASE_NAME] \ | sed -E 's/(DROP|CREATE|COMMENT ON) EXTENSION/-- \1 EXTENSION/g' > [SQL_FILE].sql
Rush

14

在这种情况下,您可以放心地忽略错误消息。未能在公共架构中添加注释并安装plpgsql(应该已经安装)不会导致任何实际问题。

但是,如果您想完全重新安装,则需要具有适当权限的用户。当然,那不应该是您的应用程序正常运行的用户。


12

简短的答案:忽略它。

该模块是Postgres处理SQL语言的一部分。该错误通常会在复制远程数据库时弹出,例如使用“ heroku pg:pull”。它不会覆盖您的SQL处理器,并对此发出警告。


9

-L通过指定从以下位置获取的文件,尝试将标志与pg_restore一起使用pg_dump -Fc

-L list-file --use-list =列表文件

仅还原列表文件中列出的那些归档元素,并按照它们在文件中出现的顺序还原它们。请注意,如果将-n或-t之类的过滤开关与-L一起使用,它们将进一步限制恢复的项目。

通常,通过编辑先前的-l操作的输出来创建列表文件。可以移动或删除行,也可以通过在行的开头放置分号(;)来注释掉行。请参阅下面的示例。

https://www.postgresql.org/docs/9.5/app-pgrestore.html

pg_dump -Fc -f pg.dump db_name
pg_restore -l pg.dump | grep -v 'COMMENT - EXTENSION' > pg_restore.list
pg_restore -L pg_restore.list pg.dump

在这里您可以通过仅输出注释来看到“ 逆”为真:

pg_dump -Fc -f pg.dump db_name
pg_restore -l pg.dump | grep 'COMMENT - EXTENSION' > pg_restore_inverse.list
pg_restore -L pg_restore_inverse.list pg.dump
--
-- PostgreSQL database dump
--

-- Dumped from database version 9.4.15
-- Dumped by pg_dump version 9.5.14

SET statement_timeout = 0;
SET lock_timeout = 0;
SET client_encoding = 'UTF8';
SET standard_conforming_strings = on;
SELECT pg_catalog.set_config('search_path', '', false);
SET check_function_bodies = false;
SET client_min_messages = warning;
SET row_security = off;

--
-- Name: EXTENSION plpgsql; Type: COMMENT; Schema: -; Owner: 
--

COMMENT ON EXTENSION plpgsql IS 'PL/pgSQL procedural language';


--
-- PostgreSQL database dump complete
--

我认为以上内容是正确的,不包括对插件的评论不会影响您应用的功能
Andreas

3

对于使用AWS的人COMMENT ON EXTENSION只有超级用户才能使用,并且正如我们的文档所知,RDS实例由Amazon管理。因此,为了防止您破坏复制之类的东西,您的用户-甚至您在创建实例时设置的root用户-都将不具有完整的超级用户特权:

http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.html

创建数据库实例时,会将您创建的主用户系统帐户分配给rds_superuser角色。rds_superuser角色是预定义的Amazon RDS角色,类似于PostgreSQL超级用户角色(在本地实例中通常称为postgres),但有一些限制。与PostgreSQL超级用户角色一样,rds_superuser角色在您的数据库实例上具有最多的特权,除非您需要对该数据库实例的最大访问权限,否则不应将该角色分配给用户。

为了解决此错误,只需使用--注释掉包含以下内容的SQL行即可COMMENT ON EXTENSION


2
或在转储时忽略评论:pg_dump --no-comments
Dmitrii I.

2

在执行还原之前,请使用postgres(admin)用户转储架构,重新创建架构并授予特权以供使用。在一个命令中:

sudo -u postgres psql -c "DROP SCHEMA public CASCADE;
create SCHEMA public;
grant usage on schema public to public;
grant create on schema public to public;" myDBName

1

对我来说,我正在使用pgAdmin设置数据库,似乎在数据库创建过程中设置所有者是不够的。我不得不导航到“公共”模式,并在那里设置所有者(最初是“ postgres”)。


0

对于已经将问题缩小为COMMENT ON语句的人员(按照下面的各种答案),并且对创建转储文件的源数据库具有超级用户访问权限的人,最简单的解决方案可能是防止将注释包含到转储中首先,通过从转储的源数据库中删除它们来...

COMMENT ON EXTENSION postgis IS NULL;
COMMENT ON EXTENSION plpgsql IS NULL;
COMMENT ON SCHEMA public IS NULL;

这样,将来的转储将不包含这些COMMENT ON语句。


1
该解决方案使我能够在Rails中进行本地开发(每当运行模式迁移时都会自动创建一个新的转储文件),该解决方案使我能够简单地rails db:reset针对AWS RDS postgresql实例运行,而不必每次运行模式时都从转储文件中删除COMMENT ON行移民。
Mark Schneider
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.