pg_restore:[存档(db)]无法执行查询:错误:模式“ public”已经存在


18

我正在使用pg_dump / pg_restore备份和还原PostgreSQL数据库,但是从pg_restore收到一些错误消息(以及非零退出状态)。我尝试了一个超级简单的基本案例(下面概述),但仍然出现以下错误:

pg_restore:[存档(db)]处理目录时出错:
pg_restore:[archiver(db)]来自TOC条目5的错误;2615 2200 SCHEMA公共邮递区号
pg_restore:[存档(db)]无法执行查询:错误:模式“ public”已经存在
    命令是:CREATE SCHEMA public;

重现步骤:

  1. 安装一个新的原始Ubuntu 14.04发行版(我正在将Vagrant与该Vagrant框一起使用)。
  2. 安装PostgreSQL 9.3,配置为允许来自任何Linux用户的PostgreSQL用户“ postgres”本地连接。
  3. 创建一个测试数据库。我只是在做:

    vagrant @ vagrant-ubuntu-trusty-64:〜$ psql --username = postgres postgres
    psql(9.3.5)
    键入“帮助”以获得帮助。
    
    postgres =#创建数据库mydb;
    创建数据库
    postgres =#\ q
    vagrant @ vagrant-ubuntu-trusty-64:〜$ psql --username = postgres mydb
    psql(9.3.5)
    键入“帮助”以获得帮助。
    
    mydb =#创建表数据(entry bigint);
    创建表
    mydb =#插入数据值(1);
    插入0 1
    mydb =#插入数据值(2);
    插入0 1
    mydb =#插入数据值(3);
    插入0 1
    mydb =#\ q
    
  4. 像这样创建数据库的备份:

    PGPASSWORD =“ postgres” pg_dump --dbname = mydb --username = postgres --format = custom> pg_backup.dump
  5. 从mydb的数据表中删除一些行,以便我们能够确定是否成功还原了数据。

  6. 使用以下方法还原数据库:

    PGPASSWORD =“ postgres” pg_restore --clean --create --dbname = postgres --username = postgres pg_backup.dump

数据已还原,但是步骤6中的pg_restore命令以状态退出1并显示以下输出:

pg_restore:[存档(db)]处理目录时出错:
pg_restore:[archiver(db)]来自TOC条目5的错误;2615 2200 SCHEMA公共邮递区号
pg_restore:[存档(db)]无法执行查询:错误:模式“ public”已经存在
    命令是:CREATE SCHEMA public;



警告:还原时忽略错误:1

我不能仅仅忽略这一点,因为我正在以编程方式运行此命令,并且需要使用退出状态来确定还原是否失败。最初,我想知道这个问题是否是因为我将数据库公开(默认架构)。我以为--createpg_restore会在还原数据之前根据该选项创建public (这可以想象也可以尝试创建该模式,因为那是我的表所在的位置),但是当我尝试对表进行上述步骤时在不同的架构中,结果是相同的,并且错误消息是相同的。

难道我做错了什么?为什么会看到此错误?

Answers:


16

该错误是无害的,但要消除该错误,我认为您需要将此恢复分为两个命令,如下所示:

dropdb -U postgres mydb && \
 pg_restore --create --dbname=postgres --username=postgres pg_backup.dump

--cleanpg_restore中的选项看起来并不多,但实际上会引发一些非凡的问题。

适用于9.1以下的版本

--create--cleanpg_restore选项的组合在以前的PG版本(最高9.1)中曾经是一个错误。两者之间确实存在一些矛盾(引用9.1联机帮助页):

--clean在重新创建数据库对象之前对其进行清理(删除)

--create在还原到数据库之前创建数据库。

因为在全新数据库中进行清理有什么意义?

从9.2版本开始

现在可以接受该组合,并且文档对此进行了说明(引用9.3联机帮助页):

--clean在重新创建数据库对象之前对其进行清理(删除)。(如果目标数据库中不存在任何对象,这可能会生成一些无害的错误消息。)

--create在还原到数据库之前创建数据库。如果还指定了--clean,请在连接到目标数据库之前删除并重新创建目标数据库。

现在,将两者放在一起会导致在还原过程中发生这种情况:

DROP DATABASE mydb;
...
CREATE DATABASE mydb WITH TEMPLATE = template0... [other options]
...
CREATE SCHEMA public;
...
CREATE TABLE...

DROP每个对象没有DROP DATABASE开头,只有一个。如果不使用,--create则相反。

无论如何,此序列都会引起public已经存在的模式错误,因为mydb从创建创建template0已经导入了它(这是正常的,这是模板数据库的关键)。

我不确定为什么这种情况不会由处理pg_restore。也许当管理员决定自定义template0和/或更改的目的时public,这会导致不良的副作用,即使我们不应该这样做。


我使用的是9.6,并指定--create没有clean不能解决的问题。
塞林

7

就我而言,原因是我使用的是pg_restore从postgresql-contrib版本11.2还原pg_dump9.6进行的转储到PostgreSQL集群9.6。

我将其降级pg_restore到9.6后,该schema "public" already exists错误消失了,还原过程像以前一样进行。


但是您是否使用pg_restore 9.6将转储还原到了postgres 11.2数据库中?
马里亚诺·鲁伊斯

@MarianoRuiz我认为我的原始答案很明确:“我使用的是来自postgresql-contrib版本11.2的pg_restore,将pg_dump 9.6进行的转储恢复到PostgreSQL集群9.6。” 因此,您的问题是:不,我没有。我的pg_restore是11.2,而pg集群是9.6
Lu Liu
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.