Création d'une copie d'une base de données dans PostgreSQL

730

Quelle est la bonne façon de copier une base de données entière (sa structure et ses données) vers une nouvelle dans pgAdmin?

egaga
la source

Réponses:

1121

Postgres autorise l'utilisation de toute base de données existante sur le serveur comme modèle lors de la création d'une nouvelle base de données. Je ne sais pas si pgAdmin vous donne l'option dans la boîte de dialogue de création de base de données, mais vous devriez pouvoir exécuter ce qui suit dans une fenêtre de requête si ce n'est pas le cas:

CREATE DATABASE newdb WITH TEMPLATE originaldb OWNER dbuser;

Pourtant, vous pouvez obtenir:

ERROR:  source database "originaldb" is being accessed by other users

Pour déconnecter tous les autres utilisateurs de la base de données, vous pouvez utiliser cette requête:

SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity 
WHERE pg_stat_activity.datname = 'originaldb' AND pid <> pg_backend_pid();
Cloche
la source
68
Notez que originaldb doit être inactif (aucune transaction d'écriture) pour que cela fonctionne.
synecdoche
62
dans pgAdmin3, dans le volet Explorateur d'objets (gauche), je peux sélectionner Servers-> (mon serveur) -> Databases, cliquer avec le bouton droit sur Bases de données et sélectionner "Nouvelle base de données". L'une des options est le modèle et le SQL utilisé pour créer la base de données est équivalent. C'est tellement plus rapide qu'une sauvegarde / restauration sur le même serveur.
jwhitlock
22
Je sais que c'est un vieux Q / A, mais je pense qu'il a besoin de clarification: lorsque @synecdoche dit que originaldb doit être inactif, cela signifie aucune possibilité d'écriture du tout. "Copier" une base de données de cette manière ne verrouille pas la base de données d'origine. PostgreSQL n'empêche le démarrage de la copie que si d'autres personnes accèdent à originaldb - pas après le démarrage de la copie, il est donc possible qu'une autre connexion puisse modifier la base de données pendant la "copie". À mon humble avis, cela peut être la réponse la plus simple, mais la "meilleure" serait d'utiliser le vidage / restauration.
Josh
10
Je viens de voir ça. @Josh: pendant que l'originaldb est copié par create database with template, postgresql ne permet pas de créer une nouvelle connexion avec lui, donc aucune modification n'est possible.
ceteras
4
Notez que si vous utilisez pgAdmin et exécutez CREATE DATABASE ... TEMPLATE xxx à partir d'une fenêtre de commande SQL, vous devez vous déconnecter de la base de données dans la fenêtre principale de pgAdmin ou vous obtiendrez l'erreur sur les utilisateurs connectés à la base de données.
Jack RG
296

Une version en ligne de commande de la réponse de Bell :

createdb -O ownername -T originaldb newdb

Cela doit être exécuté sous les privilèges du maître de base de données, généralement postgres.

zbyszek
la source
5
C'est une belle commande MAIS vous obtiendrez createdb: database creation failed: ERROR: source database "conf" is being accessed by other userssi vous essayez de le faire sur une base de données de production et comme prévu, vous ne voulez pas l'arrêter pour créer une copie.
Sorin
7
Oui, les mêmes mises en garde s'appliquent à cette commande, comme pour l'invocation CREATE DATABASE explicite. Comme le disent les commentaires sur la réponse de Bell ci-dessus, la base de données devrait être inactive.
zbyszek
108

Pour cloner une base de données existante avec postgres, vous pouvez le faire

/* KILL ALL EXISTING CONNECTION FROM ORIGINAL DB (sourcedb)*/
SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity 
WHERE pg_stat_activity.datname = 'SOURCE_DB' AND pid <> pg_backend_pid();

/* CLONE DATABASE TO NEW ONE(TARGET_DB) */
CREATE DATABASE TARGET_DB WITH TEMPLATE SOURCE_DB OWNER USER_DB;

IL va tuer toute la connexion à la base de données source en évitant l'erreur

ERROR:  source database "SOURCE_DB" is being accessed by other users
Brugolo
la source
7
+1 pour avoir mentionné une solution de script pour éviter l'erreur d'accès
bully
14
Sur Postgres 9.2, je dois remplacer procpidpar pidpour que cela fonctionne
marxjohnson
75

Dans l'environnement de production, où la base de données d'origine est sous trafic, j'utilise simplement:

pg_dump production-db | psql test-db
Tregoreg
la source
8
Un problème que j'ai trouvé avec cette méthode est que pg_dump maintiendra ouverte sa transaction jusqu'à ce que la restauration dans la nouvelle base de données soit terminée, même si pg_dump a effectivement terminé son vidage. Cela peut entraîner des problèmes de verrouillage dans certains cas (par exemple, si une instruction DDL est exécutée sur la base de données source).
Chris Butler
3
Plus un pour ne pas utiliser de fichiers intermédiaires temporaires.
Ardee Aram
C'était aussi ma solution. Hier, cela a fonctionné, maintenant les contraintes uniques aléatoires sont violées. Remarque: je laisse tomber toute la table sur le récepteur db.
gunzapper
1
@AlexanderMills pg_dump -s? postgresql.org/docs/current/static/app-pgdump.html
Tregoreg
1
Cela suppose que test-db existe. Sinon, créez la nouvelle base de données avec$ createdb newdb
SamGoody
50

Je ne connais pas pgAdmin, mais pgdumpvous donne un vidage de la base de données en SQL. Il vous suffit de créer une base de données du même nom et de faire

psql mydatabase < my dump

pour restaurer toutes les tables et leurs données et tous les privilèges d'accès.

TrayMan
la source
Merci, j'avais besoin de créer un vidage à partir d'un autre serveur, et il semble que cela aide: postgresql.org/docs/8.3/interactive/…
egaga
19
Vous pouvez même le faire, même pg_dump -U postgres sourcedb | psql -U postgres newdbsi l'efficacité de cette technique peut être mise en doute (car vous finissez probablement par changer de contexte entre les lectures et les écritures)
Frank Farmer
1
Vous pouvez même obtenir votre vidage depuis une machine distante via ssh: ssh dbserver pg_dump DBNAME | psql NEWDB... ou pg_dump DBNAME | ssh otherserver pgsql NEWDB ... Les autorisations et l'authentification doivent bien sûr être gérées comme vous le souhaitez.
ghoti
23

Tout d'abord, en sudotant qu'utilisateur de la base de données:

sudo su postgres

Accédez à la ligne de commande PostgreSQL:

psql

Créez la nouvelle base de données, donnez les droits et quittez:

CREATE DATABASE new_database_name;
GRANT ALL PRIVILEGES ON DATABASE new_database_name TO my_user;
\d

Copiez la structure et les données de l'ancienne base de données vers la nouvelle:

pg_dump old_database_name | psql new_database_name
Mathieu Rodic
la source
comment s'assurer que tout est OK même si certaines erreurs (problème réseau) se sont produites? Comment vérifier si les deux bases de données sont identiques après la migration?
BAE
Les erreurs doivent être affichées dans le terminal chaque fois qu'elles sont rencontrées. Les deux bases de données doivent être identiques après l'opération. Cependant, je ne sais pas comment vérifier ça ...
Mathieu Rodic
2
Fonctionne comme un charme, je l'ai fait pendant que la base de données était en production.
BioRod
Cela semble bien fonctionner; cependant, les deux bases de données ont une taille de disque différente via \l+. Pourquoi la différence de taille?
kosgeinsky
@kosgeinsky cela a été largement répondu ici: dba.stackexchange.com/a/102089/39386
Mathieu Rodic
18

J'ai reconstitué cette approche avec les exemples ci-dessus. Je travaille sur un serveur "sous charge" et j'ai eu l'erreur lorsque j'ai tenté l'approche de @zbyszek. J'étais également à la recherche d'une solution "en ligne de commande uniquement".

createdb: database creation failed: ERROR: source database "exampledb" is being accessed by other users.

Voici ce qui a fonctionné pour moi ( commandes précédées nohupde déplacer la sortie dans un fichier et de se protéger d'une déconnexion du serveur ):

  1. nohup pg_dump exampledb > example-01.sql
  2. createdb -O postgres exampledbclone_01

    mon utilisateur est "postgres"

  3. nohup psql exampledbclone_01 < example-01.sql

fusion27
la source
15

Dans pgAdmin, vous pouvez effectuer une sauvegarde à partir de votre base de données d'origine, puis simplement créer une nouvelle base de données et restaurer à partir de la sauvegarde que vous venez de créer:

  1. Cliquez avec le bouton droit sur la base de données source, Sauvegarde ... et sauvegardez dans un fichier.
  2. Faites un clic droit, Nouvel objet, Nouvelle base de données ... et nommez la destination.
  3. Cliquez avec le bouton droit sur la nouvelle base de données, Restaurer ... et sélectionnez votre fichier.
Isomorphe
la source
J'ai des tables liées via des clés étrangères et cela a très bien fonctionné.
Randall Blake
12

Quelle est la bonne façon de copier une base de données entière (sa structure et ses données) vers une nouvelle dans pgAdmin?

Réponse:

CREATE DATABASE newdb WITH TEMPLATE originaldb;

Essayé et testé.

Anirban Chakrabarti
la source
3
Cela nécessite que originaldb ne soit pas utilisé. La méthode d'Isomorph ne le fait pas.
Bradley
2
La même réponse a été fournie près de trois ans avant la vôtre
Jason S
8

D'après la documentation , l'utilisation createdbou CREATE DATABASEavec des modèles n'est pas encouragée:

Bien qu'il soit possible de copier une base de données autre que template1 en spécifiant son nom comme modèle, cela n'est pas (encore) conçu comme une fonction «COPY DATABASE» à usage général. La principale limitation est qu'aucune autre session ne peut être connectée à la base de données de modèles pendant sa copie. CREATE DATABASE échouera si une autre connexion existe au démarrage; sinon, les nouvelles connexions à la base de données de modèles sont verrouillées jusqu'à la fin de CREATE DATABASE.

pg_dumpou pg_dumpallest un bon moyen de copier la base de données ET TOUTES LES DONNÉES. Si vous utilisez une interface graphique comme pgAdmin, ces commandes sont appelées en arrière-plan lorsque vous exécutez une commande de sauvegarde. La copie vers une nouvelle base de données se fait en deux phases: sauvegarde et restauration

pg_dumpallenregistre toutes les bases de données du cluster PostgreSQL. L'inconvénient de cette approche est que vous vous retrouvez avec un fichier texte potentiellement très volumineux rempli de SQL requis pour créer la base de données et remplir les données. L'avantage de cette approche est que vous obtenez gratuitement tous les rôles (autorisations) du cluster. Pour vider toutes les bases de données, effectuez cette opération à partir du compte superutilisateur

pg_dumpall > db.out

et pour restaurer

psql -f db.out postgres

pg_dumpa quelques options de compression qui vous donnent des fichiers beaucoup plus petits. J'ai une base de données de production que je sauvegarde deux fois par jour avec un travail cron en utilisant

pg_dump --create --format=custom --compress=5 --file=db.dump mydatabase

compressest le niveau de compression (0 à 9) et createindique pg_dumpd'ajouter des commandes pour créer la base de données. Restaurer (ou déplacer vers un nouveau cluster) en utilisant

pg_restore -d newdb db.dump

où newdb est le nom de la base de données que vous souhaitez utiliser.

Autres choses à penser

PostgreSQL utilise ROLES pour gérer les autorisations. Ceux-ci ne sont pas copiés par pg_dump. De plus, nous n'avons pas traité les paramètres dans postgresql.conf et pg_hba.conf (si vous déplacez la base de données vers un autre serveur). Vous devrez déterminer vous-même les paramètres de conf. Mais il y a une astuce que je viens de découvrir pour sauvegarder les rôles. Les rôles sont gérés au niveau du cluster et vous pouvez demander pg_dumpallde sauvegarder uniquement les rôles avec le --roles-onlycommutateur de ligne de commande.

bfris
la source
7

PostgreSQL 9.1.2:

$ CREATEDB new_db_name -T orig_db_name -O db_user;
Arta
la source
3
Ceci est probablement implémenté car CREATE DATABASE newdb WITH TEMPLATE originaldb OWNER dbuser;, par conséquent, la base de données d'origine doit être inactive (aucune connexion avec accès en écriture) et toute nouvelle connexion à la base de données d'origine est empêchée pendant la copie. Si vous êtes satisfait de cela, cela fonctionne.
Mikko Rantalainen
Joli détail. Je vous remercie!
Arta
6

Pour ceux qui sont toujours intéressés, j'ai trouvé un script bash qui fait (plus ou moins) ce que l'auteur voulait. J'ai dû faire une copie quotidienne de la base de données d'entreprise sur un système de production, ce script semble faire l'affaire. N'oubliez pas de modifier le nom de la base de données / les valeurs utilisateur / pw.

#!/bin/bash

if [ 1 -ne $# ]
then
  echo "Usage `basename $0` {tar.gz database file}"
  exit 65;
fi

if [ -f "$1" ]
then
  EXTRACTED=`tar -xzvf $1`
  echo "using database archive: $EXTRACTED";
else
  echo "file $1 does not exist"
  exit 1
fi


PGUSER=dbuser
PGPASSWORD=dbpw
export PGUSER PGPASSWORD

datestr=`date +%Y%m%d`


dbname="dbcpy_$datestr"
createdbcmd="CREATE DATABASE $dbname WITH OWNER = postgres ENCODING = 'UTF8' TABLESPACE = pg_default LC_COLLATE = 'en_US.UTF-8' LC_CTYPE = 'en_US.UTF-8' CONNECTION LIMIT = -1;"
dropdbcmp="DROP DATABASE $dbname"

echo "creating database $dbname"
psql -c "$createdbcmd"

rc=$?
if [[ $rc != 0 ]] ; then
  rm -rf "$EXTRACTED"
  echo "error occured while creating database $dbname ($rc)"
  exit $rc
fi


echo "loading data into database"
psql $dbname < $EXTRACTED > /dev/null

rc=$?

rm -rf "$EXTRACTED"

if [[ $rc != 0 ]] ; then
  psql -c "$dropdbcmd"
  echo "error occured while loading data to database $dbname ($rc)"
  exit $rc
fi


echo "finished OK"
Dariusz
la source
5

Pour créer un vidage de base de données

cd /var/lib/pgsql/
pg_dump database_name> database_name.out

Pour resoter le vidage de la base de données

psql -d template1
CREATE DATABASE database_name WITH  ENCODING 'UTF8' LC_CTYPE 'en_US.UTF-8' LC_COLLATE 'en_US.UTF-8' TEMPLATE template0;
CREATE USER  role_name WITH PASSWORD 'password';
ALTER DATABASE database_name OWNER TO role_name;
ALTER USER role_name CREATEDB;
GRANT ALL PRIVILEGES ON DATABASE database_name to role_name;


CTR+D(logout from pgsql console)
cd /var/lib/pgsql/

psql -d database_name -f database_name.out
Jagdish Narayandasani
la source
5

Voici tout le processus de création d'une copie sur une base de données en utilisant uniquement l'interface graphique pgadmin4 (via la sauvegarde et la restauration)

Postgres est livré avec Pgadmin4. Si vous utilisez macOS, vous pouvez appuyer sur CMD+ SPACEet taper pgadmin4pour l'exécuter. Cela ouvrira un onglet de navigateur en chrome.


Étapes de copie

1. Créez la sauvegarde

Pour ce faire, cliquez avec le bouton droit sur la base de données -> "sauvegarde"

entrez la description de l'image ici

2. Donnez un nom au fichier.

Comme test12345. Cliquez sur sauvegarde. Cela crée un vidage de fichier binaire, ce n'est pas dans un .sqlformat

entrez la description de l'image ici

3. Voir où il a été téléchargé

Il devrait y avoir une fenêtre contextuelle en bas à droite de votre écran. Cliquez sur la page "plus de détails" pour voir où votre sauvegarde a été téléchargée

entrez la description de l'image ici

4. Trouvez l'emplacement du fichier téléchargé

Dans ce cas, c'est /users/vincenttang

entrez la description de l'image ici

5. Restaurez la sauvegarde à partir de pgadmin

En supposant que vous ayez effectué les étapes 1 à 4 correctement, vous aurez un fichier binaire de restauration. Il peut arriver que votre collègue veuille utiliser votre fichier de restauration sur sa machine locale. Demandez à cette personne d'aller sur pgadmin et de restaurer

Pour ce faire, cliquez avec le bouton droit sur la base de données -> "restaurer"

entrez la description de l'image ici

6. Sélectionnez le localisateur de fichiers

Assurez-vous de sélectionner l'emplacement du fichier manuellement, NE PAS faire glisser et déposer un fichier sur les champs de l'uploader dans pgadmin. Parce que vous rencontrerez des autorisations d'erreur. À la place, recherchez le fichier que vous venez de créer:

entrez la description de l'image ici

7. Trouver ledit fichier

Vous devrez peut-être modifier le filtre en bas à droite sur "Tous les fichiers". Recherchez le fichier par la suite, à partir de l'étape 4. Appuyez maintenant sur le bouton "Sélectionner" en bas à droite pour confirmer

entrez la description de l'image ici

8. Restaurer ledit fichier

Vous verrez à nouveau cette page, avec l'emplacement du fichier sélectionné. Allez-y et restaurez-le

entrez la description de l'image ici

9. Succès

Si tout va bien, le coin inférieur droit devrait afficher un indicateur indiquant une restauration réussie. Vous pouvez naviguer vers vos tables pour voir si les données ont été restaurées propery sur chaque table.

10. En cas d'échec:

Si l'étape 9 échoue, essayez de supprimer votre ancien schéma public sur votre base de données. Allez dans "Outil de requête"

entrez la description de l'image ici

Exécutez ce bloc de code:

DROP SCHEMA public CASCADE; CREATE SCHEMA public;

entrez la description de l'image ici

Maintenant, essayez à nouveau les étapes 5 à 9, cela devrait fonctionner

EDIT - Quelques notes supplémentaires. Mettez à jour PGADMIN4 si vous obtenez une erreur pendant le téléchargement avec quelque chose du type "version non prise en charge de l'en-tête 1.14 de l'archiveur" pendant la restauration

Vincent Tang
la source
3

Si la base de données a des connexions ouvertes, ce script peut vous aider. Je l'utilise pour créer une base de données de test à partir d'une sauvegarde de la base de données de production en direct tous les soirs. Cela suppose que vous disposez d'un fichier de sauvegarde .SQL de la base de données de production (je le fais dans webmin).

#!/bin/sh

dbname="desired_db_name_of_test_enviroment"
username="user_name"
fname="/path to /ExistingBackupFileOfLive.sql"

dropdbcmp="DROP DATABASE $dbname"
createdbcmd="CREATE DATABASE $dbname WITH OWNER = $username "

export PGPASSWORD=MyPassword



echo "**********"
echo "** Dropping $dbname"
psql -d postgres -h localhost -U "$username" -c "$dropdbcmp"

echo "**********"
echo "** Creating database $dbname"
psql -d postgres -h localhost -U "$username" -c "$createdbcmd"

echo "**********"
echo "** Loading data into database"
psql -d postgres -h localhost -U "$username" -d "$dbname" -a -f "$fname"
screig
la source
1

À l'aide de pgAdmin, déconnectez la base de données que vous souhaitez utiliser comme modèle. Ensuite, vous le sélectionnez comme modèle pour créer la nouvelle base de données, cela évite d'obtenir l'erreur déjà en cours d'utilisation.

evergreener2
la source
0

Si vous voulez copier tout le schéma, vous pouvez créer un pg_dump avec la commande suivante:

pg_dump -h database.host.com -d database_name -n schema_name -U database_user --password

Et lorsque vous souhaitez importer ce vidage, vous pouvez utiliser:

psql "host=database.host.com user=database_user password=database_password dbname=database_name options=--search_path=schema_name" -f sql_dump_to_import.sql

Plus d'informations sur les chaînes de connexion: https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING

Ou alors simplement en le combinant dans une doublure:

pg_dump -h database.host.com -d postgres -n schema_name -U database_user --password | psql "host=database.host.com user=database_user password=database_password dbname=database_name options=--search_path=schema_name”
Maksim Luzik
la source
0
  1. Ouvrez la fenêtre principale dans pgAdmin, puis ouvrez une autre fenêtre des outils de requête
  2. Dans les fenêtres principales de pgAdmin,

Déconnectez la base de données "modèle" que vous souhaitez utiliser comme modèle.

  1. Aller à la fenêtre des outils de requête

Exécutez 2 requêtes comme ci-dessous

SELECT pg_terminate_backend(pg_stat_activity.pid) 
    FROM pg_stat_activity 
    WHERE pg_stat_activity.datname = 'TemplateDB' AND pid <> pg_backend_pid(); 

(L'instruction SQL ci-dessus mettra fin à toutes les sessions actives avec TemplateDB, puis vous pouvez maintenant le sélectionner comme modèle pour créer la nouvelle base de données TargetDB, cela évite d'obtenir l'erreur déjà utilisée.)

CREATE DATABASE 'TargetDB'
  WITH TEMPLATE='TemplateDB'
       CONNECTION LIMIT=-1;
titushui
la source
-4

Essaye ça:

CREATE DATABASE newdb WITH ENCODING='UTF8' OWNER=owner TEMPLATE=templatedb LC_COLLATE='en_US.UTF-8' LC_CTYPE='en_US.UTF-8' CONNECTION LIMIT=-1;

gl XD

user3108031
la source