pg_restore: [archiver (db)] konnte die Abfrage nicht ausführen: FEHLER: Das Schema "public" ist bereits vorhanden

17

Ich verwende pg_dump / pg_restore zum Sichern und Wiederherstellen einer PostgreSQL-Datenbank, erhalte jedoch einige Fehlermeldungen (und einen Exit-Status ungleich Null) von pg_restore. Ich habe einen supereinfachen Basisfall ausprobiert (siehe unten), habe aber trotzdem folgende Fehler erhalten:

pg_restore: [archiver (db)] Fehler beim Verarbeiten des Inhaltsverzeichnisses:
pg_restore: [archiver (db)] Fehler von Inhaltsverzeichniseintrag 5; 2615 2200 SCHEMA öffentliche Postgres
pg_restore: [archiver (db)] konnte Abfrage nicht ausführen: FEHLER: Schema "public" existiert bereits
    Befehl war: CREATE SCHEMA public;

Schritte zum Reproduzieren:

  1. Installiere eine frische Vanille Ubuntu 14.04 Distribution (ich benutze Vagrant mit dieser Vagrant Box ).
  2. Installieren Sie PostgreSQL 9.3 und konfigurieren Sie es so, dass lokale Verbindungen von jedem Linux-Benutzer als PostgreSQL-Benutzer "postgres" zugelassen werden.
  3. Erstellen Sie eine Testdatenbank. Ich mache nur:

    vagrant @ vagrant-ubuntu-trusty-64: ~ $ psql --username = postgres postgres
    psql (9.3.5)
    Geben Sie "help" ein, um Hilfe zu erhalten.
    
    postgres = # create database mydb;
    DATENBANK ERSTELLEN
    postgres = # \ q
    vagrant @ vagrant-ubuntu-trusty-64: ~ $ psql --username = postgres mydb
    psql (9.3.5)
    Geben Sie "help" ein, um Hilfe zu erhalten.
    
    mydb = # Tabellendaten erstellen (Eintrag bigint);
    TABELLE ERSTELLEN
    mydb = # Einfügen in Datenwerte (1);
    INSERT 0 1
    mydb = # Einfügen in Datenwerte (2);
    INSERT 0 1
    mydb = # Einfügen in Datenwerte (3);
    INSERT 0 1
    mydb = # \ q
    
  4. Erstellen Sie eine Sicherungskopie der Datenbank wie folgt:

    PGPASSWORD = "postgres" pg_dump --dbname = mydb --username = postgres --format = custom> pg_backup.dump
  5. Löschen Sie einige Zeilen aus der Datentabelle in mydb, damit wir feststellen können, ob die Daten erfolgreich wiederhergestellt wurden.

  6. Stellen Sie die Datenbank wieder her mit:

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

Die Daten werden wiederhergestellt, aber der Befehl pg_restore in Schritt 6 wird mit dem Status beendet 1und zeigt die folgende Ausgabe an:

pg_restore: [archiver (db)] Fehler beim Verarbeiten des Inhaltsverzeichnisses:
pg_restore: [archiver (db)] Fehler von Inhaltsverzeichniseintrag 5; 2615 2200 SCHEMA öffentliche Postgres
pg_restore: [archiver (db)] konnte Abfrage nicht ausführen: FEHLER: Schema "public" existiert bereits
    Befehl war: CREATE SCHEMA public;



WARNUNG: Fehler, die bei der Wiederherstellung ignoriert werden: 1

Ich kann dies nicht einfach ignorieren, da ich diesen Befehl programmgesteuert ausführe und anhand des Beendigungsstatus feststellen muss, ob die Wiederherstellung fehlgeschlagen ist oder nicht. Anfangs habe ich mich gefragt, ob dieses Problem darauf zurückzuführen ist, dass ich meine Datenbank öffentlich zugänglich gemacht habe (das Standardschema). Ich dachte, dass public als Ergebnis der --createOption von pg_restore erstellt würde, bevor die Daten wiederhergestellt wurden (was möglicherweise auch versuchen könnte, dieses Schema zu erstellen, da sich dort meine Tabelle befindet), aber als ich die obigen Schritte mit meiner Tabelle ausprobierte In einem anderen Schema waren die Ergebnisse gleich und die Fehlermeldungen identisch.

Mache ich etwas falsch? Warum sehe ich diesen Fehler?

Kletmoe
quelle

Antworten:

16

Der Fehler ist harmlos, aber um ihn loszuwerden, müssen Sie diese Wiederherstellung in zwei Befehle aufteilen, wie in:

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

Die --cleanOption in pg_restore sieht nicht nach viel aus, wirft jedoch nicht-triviale Probleme auf.

Für Versionen bis 9.1

Die Kombination von --createund --cleanin pg_restore-Optionen war in älteren PG-Versionen (bis 9.1) ein Fehler. Es besteht in der Tat ein Widerspruch zwischen (unter Bezugnahme auf die Manpage 9.1):

--clean Bereinigt (löscht) Datenbankobjekte, bevor sie neu erstellt werden

und

--create Erstellen Sie die Datenbank, bevor Sie sie wiederherstellen.

Denn wozu dient die Bereinigung in einer brandneuen Datenbank?

Ab Version 9.2

Die Kombination wird jetzt akzeptiert und das Dokument sagt dies (unter Bezugnahme auf die Manpage 9.3):

--clean Bereinigt (löscht) Datenbankobjekte, bevor sie neu erstellt werden. (Dies kann zu harmlosen Fehlermeldungen führen, wenn in der Zieldatenbank keine Objekte vorhanden sind.)

--create Erstellen Sie die Datenbank, bevor Sie sie wiederherstellen. Wenn auch --clean angegeben ist, löschen Sie die Zieldatenbank und erstellen Sie sie erneut, bevor Sie eine Verbindung herstellen.

Wenn Sie nun beides zusammen haben, führt dies zu dieser Art von Sequenz während der Wiederherstellung:

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

DROPFür jedes einzelne Objekt gibt es kein , nur ein DROP DATABASEam Anfang. Wenn nicht, --createwäre dies das Gegenteil.

Auf jeden Fall löst diese Sequenz den Fehler des publicbereits vorhandenen Schemas aus, da das Erstellen mydbaus template0es bereits importiert hat (was normal ist, es ist der Punkt einer Vorlagendatenbank).

Ich bin nicht sicher, warum dieser Fall nicht automatisch von behandelt wird pg_restore. Vielleicht würde dies unerwünschte Nebenwirkungen verursachen, wenn ein Administrator beschließt, template0den Zweck von anzupassen und / oder zu ändern public, selbst wenn wir das nicht tun sollen.

Daniel Vérité
quelle
Ich verwende 9.6 und die Angabe --createohne cleanbehebt das Problem nicht.
Cerin
6

In meinem Fall lag der Grund darin, dass ich mit pg_restorepostgresql-contrib Version 11.2 einen von pg_dump9.6 erstellten Dump in einem PostgreSQL-Cluster 9.6 wiederhergestellt habe .

Nachdem ich mein pg_restoreBack auf 9.6 heruntergestuft hatte , war dieser schema "public" already existsFehler behoben und der Wiederherstellungsprozess funktionierte wie zuvor.

Lu Liu
quelle
Aber haben Sie den Dump mit pg_restore 9.6 in einer Postgres 11.2-Datenbank wiederhergestellt?
Mariano Ruiz
@MarianoRuiz Ich denke, meine ursprüngliche Antwort ist klar: "Ich habe pg_restore aus postgresql-contrib Version 11.2 verwendet, um einen von pg_dump 9.6 erstellten Speicherauszug in einem PostgreSQL-Cluster 9.6 wiederherzustellen." Also zu deiner Frage: Nein, habe ich nicht. Mein pg_restore war 11,2, während der pg-Cluster 9,6 war
Lu Liu