pg_restore: [archiver (db)] não pôde executar a consulta: ERRO: o esquema “público” já existe

17

Estou usando pg_dump / pg_restore para fazer backup e restaurar um banco de dados PostgreSQL, mas estou recebendo algumas mensagens de erro (e um status de saída diferente de zero) do pg_restore. Eu tentei um caso básico super simples (descrito abaixo), mas ainda assim tenho esses erros:

pg_restore: [archiver (db)] Erro ao processar o sumário:
pg_restore: [archiver (db)] Erro da entrada 5 do TOC; 2615 2200 SCHEMA postgres públicos
pg_restore: [archiver (db)] não pôde executar a consulta: ERRO: o esquema "público" já existe
    O comando foi: CREATE SCHEMA public;

Passos para reproduzir:

  1. Instale uma nova distro de baunilha do Ubuntu 14.04 (estou usando o Vagrant com esta caixa do Vagrant ).
  2. Instale o PostgreSQL 9.3, configure para permitir conexões locais como usuário do PostgreSQL "postgres" de qualquer usuário do Linux.
  3. Crie um banco de dados de teste. Eu estou apenas fazendo:

    vagrant @ vagrant-ubuntu-trusty-64: ~ $ psql --username = postgres postgres
    psql (9.3.5)
    Digite "ajuda" para obter ajuda.
    
    postgres = # cria banco de dados mydb;
    CRIAR BASE DE DADOS
    postgres = # \ q
    vagrant @ vagrant-ubuntu-trusty-64: ~ $ psql --username = postgres mydb
    psql (9.3.5)
    Digite "ajuda" para obter ajuda.
    
    mydb = # cria dados da tabela (entrada bigint);
    CRIAR A TABELA
    mydb = # insere valores de dados (1);
    INSERIR 0 1
    mydb = # insere valores de dados (2);
    INSERIR 0 1
    mydb = # insere valores de dados (3);
    INSERIR 0 1
    mydb = # \ q
    
  4. Crie um backup do banco de dados da seguinte forma:

    PGPASSWORD = "postgres" pg_dump --dbname = mydb --username = postgres --format = customizado> pg_backup.dump
  5. Exclua algumas linhas da tabela de dados em mydb para podermos saber se restauramos os dados com êxito.

  6. Restaure o banco de dados com:

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

Os dados são restaurados, mas o comando pg_restore na etapa 6 sai com status 1e mostra a seguinte saída:

pg_restore: [archiver (db)] Erro ao processar o sumário:
pg_restore: [archiver (db)] Erro da entrada 5 do TOC; 2615 2200 SCHEMA postgres públicos
pg_restore: [archiver (db)] não pôde executar a consulta: ERRO: o esquema "público" já existe
    O comando foi: CREATE SCHEMA public;



AVISO: erros ignorados na restauração: 1

Não posso simplesmente ignorar isso porque estou executando este comando programaticamente e preciso usar o status de saída para determinar se a restauração falhou ou não. Inicialmente, eu me perguntava se esse problema era porque eu coloquei meu banco de dados em público (o esquema padrão). Eu raciocinei que o público seria criado como resultado da --createopção pelo pg_restore antes da restauração dos dados (o que poderia tentar criar esse esquema também, pois é onde está minha tabela), mas quando tentei as etapas acima com minha tabela em um esquema diferente, os resultados eram os mesmos e as mensagens de erro eram idênticas.

Estou fazendo algo errado? Por que estou vendo esse erro?

KSletmoe
fonte

Respostas:

16

O erro é inofensivo, mas para se livrar dele, acho que você precisa dividir essa restauração em dois comandos, como em:

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

A --cleanopção no pg_restore não parece muito, mas na verdade levanta problemas não triviais.

Para versões até 9.1

A combinação das opções --createe --cleannas opções pg_restore costumava ser um erro nas versões mais antigas do PG (até 9.1). De fato, há alguma contradição entre (citando a página de manual 9.1):

--clean Limpa (descarta) objetos do banco de dados antes de recriá-los

e

--create Crie o banco de dados antes de restaurá-lo.

Porque qual é o sentido de limpar dentro de um banco de dados totalmente novo?

A partir da versão 9.2

A combinação agora é aceita e o documento diz o seguinte (citando a página de manual 9.3):

--clean Limpe (solte) objetos de banco de dados antes de recriá-los. (Isso pode gerar algumas mensagens de erro inofensivas, se algum objeto não estiver presente no banco de dados de destino.)

--create Crie o banco de dados antes de restaurá-lo. Se --clean também for especificado, descarte e recrie o banco de dados de destino antes de conectar-se a ele.

Agora, ter os dois juntos leva a esse tipo de sequência durante a restauração:

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

Não existe DROPpara cada objeto individual, apenas um DROP DATABASEno início. Se não estiver usando --createisso seria o oposto.

De qualquer forma, essa sequência gera o erro do publicesquema já existente porque a criação mydbde template0já foi importada (o que é normal, é o ponto de um banco de dados de modelos).

Não sei por que esse caso não é tratado automaticamente por pg_restore. Talvez isso cause efeitos colaterais indesejáveis ​​quando um administrador decide personalizar template0e / ou alterar o objetivo public, mesmo que não devamos fazer isso.

Daniel Vérité
fonte
Estou usando o 9.6 e especificar --createsem cleannão resolve o problema.
Cerin 29/11
6

No meu caso, o motivo foi que eu estava usando o pg_restorepostgresql-contrib versão 11.2 para restaurar um dump feito pelo pg_dump9.6 para um cluster do PostgreSQL 9.6.

Depois de pg_restorevoltar para a 9.6, esse schema "public" already existserro desapareceu e o processo de restauração funcionou como antes.

Lu Liu
fonte
Mas você restaurou o dump usando o pg_restore 9.6 em um banco de dados do postgres 11.2?
Mariano Ruiz
@MarianoRuiz Acho que minha resposta original é clara: "Eu estava usando o pg_restore da versão 11.2 do postgresql-contrib para restaurar um dump feito pelo pg_dump 9.6 para um cluster do PostgreSQL 9.6." Então, para sua pergunta: não, eu não fiz. Meu pg_restore foi de 11,2, enquanto o cluster pg foi de 9,6
Lu Liu