pg_restore: [archiver (db)] no pudo ejecutar la consulta: ERROR: el esquema "público" ya existe

17

Estoy usando pg_dump / pg_restore para hacer una copia de seguridad y restaurar una base de datos PostgreSQL, pero recibo algunos mensajes de error (y un estado de salida distinto de cero) de pg_restore. Intenté un caso base súper simple (descrito a continuación) pero aún obtuve estos errores:

pg_restore: [archiver (db)] Error al PROCESAR TOC:
pg_restore: [archiver (db)] Error de la entrada 5 de TOC; 2615 2200 SCHEMA public postgres
pg_restore: [archiver (db)] no pudo ejecutar la consulta: ERROR: el esquema "público" ya existe
    El comando era: CREAR ESQUEMA público;

Pasos para reproducir:

  1. Instale una distribución Ubuntu 14.04 nueva y vainilla (estoy usando Vagrant con esta caja Vagrant ).
  2. Instale PostgreSQL 9.3, configúrelo para permitir conexiones locales como usuario de PostgreSQL "postgres" de cualquier usuario de Linux.
  3. Crea una base de datos de prueba. Solo estoy haciendo:

    vagrant @ vagrant-ubuntu-trusty-64: ~ $ psql --username = postgres postgres
    psql (9.3.5)
    Escriba "ayuda" para obtener ayuda.
    
    postgres = # crear base de datos mydb;
    CREAR BASE DE DATOS
    postgres = # \ q
    vagrant @ vagrant-ubuntu-trusty-64: ~ $ psql --username = postgres mydb
    psql (9.3.5)
    Escriba "ayuda" para obtener ayuda.
    
    mydb = # crear datos de tabla (entrada bigint);
    CREAR MESA
    mydb = # insertar en valores de datos (1);
    INSERTAR 0 1
    mydb = # insertar en valores de datos (2);
    INSERTAR 0 1
    mydb = # insertar en valores de datos (3);
    INSERTAR 0 1
    mydb = # \ q
    
  4. Cree una copia de seguridad de la base de datos de esta manera:

    PGPASSWORD = "postgres" pg_dump --dbname = mydb --username = postgres --format = custom> pg_backup.dump
  5. Elimine algunas filas de la tabla de datos en mydb para que podamos saber si restauramos los datos con éxito.

  6. Restaurar la base de datos con:

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

Los datos se restauran, pero el comando pg_restore en el paso 6 sale con el estado 1y muestra la siguiente salida:

pg_restore: [archiver (db)] Error al PROCESAR TOC:
pg_restore: [archiver (db)] Error de la entrada 5 de TOC; 2615 2200 SCHEMA public postgres
pg_restore: [archiver (db)] no pudo ejecutar la consulta: ERROR: el esquema "público" ya existe
    El comando era: CREAR ESQUEMA público;



ADVERTENCIA: errores ignorados en la restauración: 1

No puedo simplemente ignorar esto porque estoy ejecutando este comando mediante programación y necesito usar el estado de salida para determinar si la restauración falló o no. Inicialmente, me preguntaba si este problema se debía a que puse mi base de datos en público (el esquema predeterminado). Pensé que --createpg_restore crearía público como resultado de la opción antes de que se restauraran los datos (lo que posiblemente podría intentar crear ese esquema también, ya que es donde está mi tabla), pero cuando intenté los pasos anteriores con mi tabla en un esquema diferente, los resultados fueron los mismos y los mensajes de error fueron idénticos.

¿Estoy haciendo algo mal? ¿Por qué veo este error?

KSletmoe
fuente

Respuestas:

16

El error es inofensivo, pero para deshacerme de él, creo que debe dividir esta restauración en dos comandos, como en:

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

La --cleanopción en pg_restore no parece mucho, pero en realidad plantea problemas no triviales.

Para versiones hasta 9.1

La combinación de --createy --cleanen las opciones de pg_restore solía ser un error en versiones anteriores de PG (hasta 9.1). De hecho, existe cierta contradicción entre (citando la página del manual 9.1):

--limpie los objetos de la base de datos antes de volver a crearlos

y

--create Crea la base de datos antes de restaurarla.

Porque, ¿de qué sirve limpiar dentro de una nueva base de datos?

A partir de la versión 9.2

La combinación ahora se acepta y el documento dice esto (citando la página de manual 9.3):

--limpie Limpie (suelte) los objetos de la base de datos antes de recrearlos. (Esto podría generar algunos mensajes de error inofensivos, si algún objeto no estuviera presente en la base de datos de destino).

--create Crea la base de datos antes de restaurarla. Si también se especifica --clean, suelte y vuelva a crear la base de datos de destino antes de conectarse a ella.

Ahora, tener ambos juntos conduce a este tipo de secuencia durante su restauración:

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

No hay DROPpara cada objeto individual, solo un DROP DATABASEal principio. Si no usa --createesto sería lo contrario.

De todos modos, esta secuencia genera el error de publicesquema ya existente porque crear mydbdesde template0ya lo ha importado (lo cual es normal, es el punto de una base de datos de plantilla).

No estoy seguro de por qué este caso no se maneja automáticamente pg_restore. Tal vez esto podría causar efectos secundarios indeseables cuando un administrador decide personalizar template0y / o cambiar el propósito de public, incluso si no se supone que lo hagamos.

Daniel Vérité
fuente
Estoy usando 9.6, y especificar --createsin cleanno soluciona el problema.
Cerin
6

En mi caso, la razón fue que estaba usando pg_restorepostgresql-contrib versión 11.2 para restaurar un volcado realizado por pg_dump9.6 en un clúster PostgreSQL 9.6.

Después de que bajé mi pg_restoreversión a 9.6, este schema "public" already existserror desapareció y el proceso de restauración funcionó como antes.

Lu Liu
fuente
¿Pero restauró el volcado usando pg_restore 9.6 en una base de datos postgres 11.2?
Mariano Ruiz
@MarianoRuiz Creo que mi respuesta original es clara: "Estaba usando pg_restore de postgresql-contrib versión 11.2 para restaurar un volcado realizado por pg_dump 9.6 en un clúster PostgreSQL 9.6". Entonces a su pregunta: No, no lo hice. Mi pg_restore fue 11.2 mientras que el clúster pg fue 9.6
Lu Liu