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:
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
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
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.
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?
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.
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.
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
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