web-dev-qa-db-fra.com

pg_restore: [archiveur (db)] n'a pas pu exécuter la requête: ERREUR: le schéma "public" existe déjà

J'utilise pg_dump/pg_restore pour sauvegarder et restaurer une base de données PostgreSQL, mais je reçois des messages d'erreur (et un état de sortie non nul) de pg_restore. J'ai essayé un cas de base super simple (décrit ci-dessous) mais j'ai toujours ces erreurs:

 pg_restore: [archiver (db)] Erreur lors du TRAITEMENT DE LA COT: 
 pg_restore: [archiver (db)] Erreur de l'entrée 5 de la table des matières; 2615 2200 SCHEMA public postgres 
 Pg_restore: [l'archiveur (db)] n'a pas pu exécuter la requête: ERREUR: le schéma "public" existe déjà 
 La commande était: CREATE SCHEMA public; 

Étapes à reproduire:

  1. Installez une nouvelle distribution Vanilla Ubuntu 14.04 (j'utilise Vagrant avec cette boîte Vagrant ).
  2. Installez PostgreSQL 9.3, configurez pour autoriser les connexions locales en tant qu'utilisateur PostgreSQL "postgres" de n'importe quel utilisateur Linux.
  3. Créez une base de données de test. Je fais juste:

     vagrant @ vagrant-ubuntu-trusty-64: ~ $ psql --username = postgres postgres 
     psql (9.3.5) 
     Tapez "help" pour obtenir de l'aide. 
     
     postgres = # create database mydb; 
     CREATE DATABASE 
     postgres = #\q 
     vagrant @ vagrant-ubuntu-trusty-64: ~ $ psql - -username = postgres mydb 
     psql (9.3.5) 
     Tapez "help" pour obtenir de l'aide. 
     
     mydb = # créer des données de table (entrée bigint); 
     CRÉER UN TABLEAU 
     Mydb = # insérer dans les valeurs de données (1); 
     INSÉRER 0 1 
     Mydb = # insérer dans les valeurs de données (2); 
     INSÉRER 0 1 
     Mydb = # insérer dans les valeurs de données (3); 
     INSÉRER 0 1 
     Mydb = #\q 
    
  4. Créez une sauvegarde de la base de données comme ceci:

    PGPASSWORD = "postgres" pg_dump --dbname = mydb --username = postgres --format = custom> pg_backup.dump
  5. Supprimez certaines lignes du tableau de données dans mydb afin que nous puissions savoir si nous avons restauré les données avec succès.

  6. Restaurez la base de données avec:

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

Les données sont restaurées, mais la commande pg_restore à l'étape 6 se termine avec le statut 1 et affiche la sortie suivante:

 pg_restore: [archiver (db)] Erreur lors du TRAITEMENT DE LA COT: 
 pg_restore: [archiver (db)] Erreur de l'entrée 5 de la table des matières; 2615 2200 SCHEMA public postgres 
 Pg_restore: [l'archiveur (db)] n'a pas pu exécuter la requête: ERREUR: le schéma "public" existe déjà 
 La commande était: CREATE SCHEMA public; 
 
 
 
 AVERTISSEMENT: erreurs ignorées lors de la restauration: 1 

Je ne peux pas simplement ignorer cela car j'exécute cette commande par programme et j'ai besoin d'utiliser l'état de sortie pour déterminer si la restauration a échoué ou non. Au départ, je me demandais si ce problème était dû au fait que je mettais ma base de données en public (le schéma par défaut). J'ai pensé que le public serait créé à la suite du --create option de pg_restore avant que les données ne soient restaurées (ce qui pourrait éventuellement essayer de créer ce schéma aussi puisque c'est là que se trouve ma table), mais quand j'ai essayé les étapes ci-dessus avec ma table dans un schéma différent, les résultats étaient les mêmes et les messages d'erreur étaient identiques.

Est-ce que je fais quelque chose de mal? Pourquoi est-ce que je vois cette erreur?

20
KSletmoe

L'erreur est inoffensive mais pour s'en débarrasser, je pense que vous devez diviser cette restauration en deux commandes, comme dans:

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

L'option --clean Dans pg_restore ne ressemble pas à grand-chose mais pose en fait des problèmes non triviaux.

Pour les versions jusqu'à 9.1

La combinaison de --create Et --clean Dans les options de pg_restore était une erreur dans les anciennes versions de PG (jusqu'à 9.1). Il y a en effet une certaine contradiction entre (citant la page de manuel 9.1):

- nettoyer les objets de la base de données Clean (drop) avant de les recréer

et

--créer Créez la base de données avant de la restaurer.

Car à quoi bon nettoyer une nouvelle base de données?

à partir de la version 9.2

La combinaison est maintenant acceptée et le doc le dit (en citant la page de manuel 9.3):

--clean Nettoyer (supprimer) les objets de base de données avant de les recréer. (Cela pourrait générer des messages d'erreur inoffensifs, si aucun objet n'était présent dans la base de données de destination.)

--créer Créez la base de données avant de la restaurer. Si --clean est également spécifié, supprimez et recréez la base de données cible avant de vous y connecter.

Maintenant, avoir les deux ensemble conduit à ce type de séquence lors de votre restauration:

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

Il n'y a pas de DROP pour chaque objet individuel, seulement un DROP DATABASE Au début. Si vous n'utilisez pas --create, Ce serait le contraire.

Quoi qu'il en soit, cette séquence soulève l'erreur du schéma public déjà existant car la création de mydb à partir de template0 L'a déjà importé (ce qui est normal, c'est le point d'une base de données de modèles).

Je ne sais pas pourquoi ce cas n'est pas traité automatiquement par pg_restore. Peut-être que cela provoquerait des effets secondaires indésirables lorsqu'un administrateur déciderait de personnaliser template0 Et/ou de changer l'objectif de public, même si nous ne sommes pas censés le faire.

17
Daniel Vérité

Dans mon cas, la raison était que j'utilisais pg_restore à partir de la version 11.2 de postgresql-contrib pour restaurer un vidage effectué par pg_dump 9.6 vers un cluster PostgreSQL 9.6.

Après avoir rétrogradé mon pg_restore retour à 9.6, ce schema "public" already exists l'erreur a disparu et le processus de restauration a fonctionné comme auparavant.

7
Lu Liu

La restauration inclut le schéma public et crée donc la base de données. Supprimez donc le schéma après avoir créé la base de données afin que la restauration puisse le créer sans erreur.

Remarque: La suite suppose que -h -U -p est par défaut et PGPASSWORD ou .pgpass est défini

    psql << XENDX
    drop database if exists DB_NAME;
    create database DB_NAME;
    /c DB_NAME;
    drop schema if exists public;
    create schema public;
    XENX

    pg_restore -d DB_NAME FILE_CREATED_WITH_pg_dump
1
DaJudge

Je l'ai résolu avec:

dans le db.sql fichier

drop database if exists DB_name;
create database DB_name;
drop schema if exists public;
create schema public;
\q

puis

PGPASSWOD=DB_pass psql -U DB_user -h 127.0.0.1 < db.sql

Et alors

PGPASSWOD=DB_pass pg_restore -h 127.0.0.1 \ 
    -U DB_user -d DB_name --create --no-acl --no-owner DB_dump_FILE

Ma version pg_restore est 11.6

0
user9869932