【问题标题】:How to solve privileges issues when restore PostgreSQL Database恢复 PostgreSQL 数据库时如何解决权限问题
【发布时间】:2012-11-04 19:50:26
【问题描述】:

我已经使用命令为 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

我深入研究了pg_dump 生成的纯文本 SQL,发现它包含 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 的权限。

我该如何解决这个问题?

【问题讨论】:

  • 如果你不需要plpgsql,那么DROP EXTENSION plpgsql在你之前pg_dump。这比让你的应用程序成为超级用户更安全,也比忽略错误更方便(如果你使用--single-transaction-v ON_ERROR_STOP=1 会爆炸)。这是一个已知问题,[由 Postgres 开发人员详细讨论|postgresql.org/message-id/…,但在 9.3 中尚未修复。

标签: postgresql database-backups rails-postgresql


【解决方案1】:

一些答案​​已经提供了与摆脱创建扩展和评论扩展相关的各种方法。对我来说,以下命令行似乎有效,并且是解决问题的最简单方法:

cat /tmp/backup.sql.gz | gunzip - | \
  grep -v -E '(CREATE\ EXTENSION|COMMENT\ ON)' |  \
    psql --set ON_ERROR_STOP=on -U db_user -h localhost my_db

一些笔记

  • 第一行只是解压缩我的备份,您可能需要进行相应调整。
  • 第二行是使用 grep 删除违规行。
  • 第三行是我的psql命令;您可能需要像通常使用 psql 进行恢复一样进行调整。

【讨论】:

    【解决方案2】:

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

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

    未来的转储将不包括 COMMENT ON 语句。

    【讨论】:

    • 在 Rails 中本地开发(每当运行架构迁移时会自动创建一个新的转储文件),此解决方案使我能够简单地针对 AWS RDS postgresql 实例运行rails db:reset,而无需删除 COMMENT ON每次我运行模式迁移时转储文件中的行。
    【解决方案3】:

    对于使用 AWS 的人,COMMENT ON EXTENSION 只能作为 超级用户 使用,并且正如我们从文档中知道的那样,RDS 实例由 Amazon 管理。因此,为防止您破坏复制等操作,您的用户(甚至是您在创建实例时设置的 root 用户)将不具有完全的超级用户权限:

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

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

    为了修复这个错误,只需使用--注释掉包含COMMENT ON EXTENSION的SQL行

    【讨论】:

    • 或者在转储时省略 cmets:pg_dump --no-comments.
    【解决方案4】:

    通过指定取自 pg_dump -Fc 的文件,尝试将 -L 标志与 pg_restore 一起使用

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

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

    list-file 通常是通过编辑前一个 -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
    

    在这里您可以通过仅输出评论看到 Inverse 为真:

    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
    --
    

    【讨论】:

    • 我觉得上面说的是对的,排除插件的cmets不会影响你应用的功能
    • 这绝对是最好的答案,不知道为什么它下面的两个答案说简单地忽略它......
    【解决方案5】:

    对于使用 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 docs 中提供的命令、当前线程中的提示或 Google Postgres 团队here 的建议来解决。其中建议发出以下命令:

    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

    【讨论】:

    • GCP 现在可以在其docs 中使用确切的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
    • 我必须在 plgsql 单词中使用双引号,例如 grep 命令上的"plpgsql" 才能完成这项工作。
    【解决方案6】:

    对我来说,我正在使用 pgAdmin 设置数据库,但在创建数据库期间设置所有者似乎还不够。我不得不向下导航到 'public' 架构,并将 owner 也设置在那里(最初是 'postgres')。

    【讨论】:

      【解决方案7】:

      AWS RDS 用户如果您收到此信息,那是因为您不是超级用户,并且根据 aws 文档,您不能成为超级用户。我发现我必须忽略这些错误。

      【讨论】:

      • 此错误阻止我完成还原 (AWS RDS pg_restore)。有什么提示可以忽略这些错误吗?
      • P.S.我没有对 pg_restore 使用 -e 或 --exit-on-error
      • 我发现,在 RDS 上,问题是 COMMENT ON EXTENSION,而不是 CREATE EXTENSION。移除 cmets,你应该会没事的。
      • @pkoch 与谷歌云存储相同。对扩展的评论是问题,不需要
      • 用这个pg_restore --list $DUMP_DIR | sed '/COMMENT - EXTENSION/d' > $DUMP_ROOT/restore.list过滤cmets然后用这个pg_restore --dbname $CONN --verbose --exit-on-error --use-list $DUMP_ROOT/restore.list --no-owner --role=$DBUSER --clean --if-exists $DUMP_DIR运行恢复
      【解决方案8】:

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

      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 &lt;user-name&gt; Superuser; 语句。

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

      【讨论】:

      • 有没有办法在不成为超级用户的情况下做到这一点?
      • “必须分配适当的所有权权限”和“alter role superuser”不一致。正确的所有权意味着app_user不是超级用户。
      • @mehaase 请更新答案的措辞,而不是反对投票。
      • 恕我直言,这不是解决方案,而是在生产中应避免的解决方法。
      • 做普通用户superuser是个坏建议
      【解决方案9】:

      使用 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
      

      【讨论】:

        【解决方案10】:

        简短的回答:忽略它。

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

        【讨论】:

          【解决方案11】:

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

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

          【讨论】:

            猜你喜欢
            • 2020-07-07
            • 1970-01-01
            • 2010-09-21
            • 2021-11-21
            • 2013-11-15
            • 2011-10-13
            • 2014-12-20
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多