Erstellen einer Kopie einer Datenbank in PostgreSQL

728

Was ist der richtige Weg, um die gesamte Datenbank (ihre Struktur und Daten) in eine neue in pgAdmin zu kopieren?

egaga
quelle

Antworten:

1120

Postgres ermöglicht die Verwendung einer auf dem Server vorhandenen Datenbank als Vorlage beim Erstellen einer neuen Datenbank. Ich bin nicht sicher, ob pgAdmin Ihnen die Option im Dialogfeld "Datenbank erstellen" bietet, aber Sie sollten in der Lage sein, Folgendes in einem Abfragefenster auszuführen, wenn dies nicht der Fall ist:

CREATE DATABASE newdb WITH TEMPLATE originaldb OWNER dbuser;

Dennoch können Sie erhalten:

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

Um alle anderen Benutzer von der Datenbank zu trennen, können Sie folgende Abfrage verwenden:

SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity 
WHERE pg_stat_activity.datname = 'originaldb' AND pid <> pg_backend_pid();
Glocke
quelle
68
Beachten Sie, dass originaldb inaktiv sein muss (keine Schreibtransaktionen), damit dies funktioniert.
Synecdoche
62
In pgAdmin3 kann ich im Bereich Objektbrowser (links) Servers-> (mein Server) -> Databasesauswählen, mit der rechten Maustaste auf Datenbanken klicken und "Neue Datenbank" auswählen. Eine der Optionen ist die Vorlage, und das zum Erstellen der Datenbank verwendete SQL ist äquivalent. Es ist so viel schneller als ein Dump / Restore auf demselben Server.
Jwhitlock
22
Ich weiß, dass dies ein altes Q / A ist, aber ich denke, es muss geklärt werden: Wenn @synecdoche sagt, dass originaldb untätig sein muss, bedeutet dies, dass überhaupt keine Schreibmöglichkeit besteht. Das "Kopieren" einer Datenbank auf diese Weise sperrt originaldb nicht. PostgreSQL verhindert das Starten der Kopie nur, wenn andere Benutzer auf originaldb zugreifen - nicht nach dem Start der Kopie. Daher kann eine andere Verbindung die Datenbank möglicherweise ändern, während die "Kopie" ausgeführt wird. IMHO, dies mag die einfachste Antwort sein, aber das "Beste" wäre, Dump / Restore zu verwenden.
Josh
10
Ich habe das gerade gesehen. @Josh: Während das Originaldb kopiert wird, indem eine Datenbank mit Vorlage erstellt wird, erlaubt postgresql nicht, eine neue Verbindung dazu herzustellen, sodass keine Änderungen möglich sind.
ceteras
4
Beachten Sie, dass Sie, wenn Sie pgAdmin verwenden und CREATE DATABASE ... TEMPLATE xxx in einem SQL-Befehlsfenster ausführen, die Verbindung zur Datenbank im Hauptfenster von pgAdmin trennen müssen, da sonst die Fehlermeldung angezeigt wird, dass Benutzer mit der Datenbank verbunden sind.
Jack RG
296

Eine Befehlszeilenversion von Bells Antwort :

createdb -O ownername -T originaldb newdb

Dies sollte unter den Berechtigungen des Datenbankmasters ausgeführt werden, normalerweise postgres.

zbyszek
quelle
5
Dies ist ein netter Befehl, den Sie jedoch erhalten, createdb: database creation failed: ERROR: source database "conf" is being accessed by other userswenn Sie versuchen, ihn in einer Produktionsdatenbank auszuführen, und Sie ihn erwartungsgemäß nicht herunterfahren möchten, um eine Kopie zu erstellen.
Sorin
7
Ja, für diesen Befehl gelten dieselben Einschränkungen wie für den expliziten Aufruf von CREATE DATABASE. Wie in den Kommentaren zu Bells Antwort oben angegeben, sollte die Datenbank inaktiv sein.
Zbyszek
108

Um eine vorhandene Datenbank mit Postgres zu klonen, können Sie dies tun

/* 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;

Die IT beendet die gesamte Verbindung zur Quelldatenbank, um den Fehler zu vermeiden

ERROR:  source database "SOURCE_DB" is being accessed by other users
Brugolo
quelle
7
+1 für die Erwähnung einer Skriptlösung, um den Zugriffsfehler zu vermeiden
Mobbing
14
Auf Postgres 9.2 muss ich ersetzen procpidmit pidfür diese Arbeit
marxjohnson
75

In einer Produktionsumgebung, in der die ursprüngliche Datenbank unter Datenverkehr steht, verwende ich einfach:

pg_dump production-db | psql test-db
Tregoreg
quelle
8
Ein Problem, das ich bei dieser Methode festgestellt habe, ist, dass pg_dump seine Transaktion offen hält, bis die Wiederherstellung in der neuen Datenbank abgeschlossen ist, selbst wenn pg_dump den Speicherauszug tatsächlich abgeschlossen hat. Dies kann in einigen Fällen zu Sperrproblemen führen (z. B. wenn eine DDL-Anweisung in der Quelldatenbank ausgeführt wird).
Chris Butler
3
Plus eine für die Nichtverwendung temporärer Zwischendateien.
Ardee Aram
Es war auch meine Lösung. Gestern hat es funktioniert, jetzt werden zufällige eindeutige Einschränkungen verletzt. Hinweis: Ich lege alle Tabellen auf Empfänger db.
Gunzapper
1
@ AlexanderMills pg_dump -s? postgresql.org/docs/current/static/app-pgdump.html
Tregoreg
1
Dies setzt voraus, dass test-db existiert. Andernfalls erstellen Sie die neue $ createdb newdb
Datenbank
50

Sie kennen pgAdmin nicht, pgdumpgeben Ihnen jedoch einen Speicherauszug der Datenbank in SQL. Sie müssen nur eine Datenbank mit demselben Namen erstellen und dies tun

psql mydatabase < my dump

um alle Tabellen und ihre Daten sowie alle Zugriffsrechte wiederherzustellen.

TrayMan
quelle
Danke, ich musste einen Dump von einem anderen Server erstellen, und es scheint, dass dies hilft: postgresql.org/docs/8.3/interactive/…
egaga
19
Sie können dies sogar tun, pg_dump -U postgres sourcedb | psql -U postgres newdbobwohl die Effizienz dieser Technik fraglich sein kann (da Sie wahrscheinlich den Kontext zwischen Lesen und Schreiben wechseln)
Frank Farmer
1
Sie können Ihren Speicherauszug sogar über ssh von einem Remotecomputer abrufen: ssh dbserver pg_dump DBNAME | psql NEWDB... oder pg_dump DBNAME | ssh otherserver pgsql NEWDB ... Berechtigungen und Authentifizierung müssen natürlich behandelt werden, wie Sie möchten.
Ghoti
23

Erstens sudoals Datenbankbenutzer:

sudo su postgres

Gehen Sie zur PostgreSQL-Befehlszeile:

psql

Erstellen Sie die neue Datenbank, geben Sie die Rechte ein und beenden Sie:

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

Kopieren Sie Struktur und Daten aus der alten Datenbank in die neue:

pg_dump old_database_name | psql new_database_name
Mathieu Rodic
quelle
Wie kann man sicherstellen, dass alles in Ordnung ist, auch wenn einige Fehler (Netzwerkproblem) aufgetreten sind? Wie kann ich überprüfen, ob die beiden Datenbanken nach der Migration identisch sind?
BAE
Fehler sollten im Terminal angezeigt werden, wenn sie auftreten. Die beiden Datenbanken sollten nach dem Vorgang identisch sein. Ich weiß jedoch nicht, wie ich das überprüfen soll ...
Mathieu Rodic
2
Funktioniert wie ein Zauber, ich habe es getan, während die Datenbank in Produktion war.
BioRod
Dies scheint gut zu funktionieren; Die beiden Datenbanken haben jedoch unterschiedliche Datenträgergrößen über \l+. Warum der Größenunterschied?
Kosgeinsky
@ Kosgeinsky Dies wurde hier ausführlich beantwortet: dba.stackexchange.com/a/102089/39386
Mathieu Rodic
18

Ich habe diesen Ansatz mit den Beispielen von oben zusammengesetzt. Ich arbeite an einem "unter Last" -Server und habe den Fehler erhalten, als ich den Ansatz von @zbyszek aus versuchte. Ich war auch nach einer "Kommandozeilen" -Lösung.

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

Folgendes hat beinohup mir funktioniert ( Befehle, denen vorangestellt wurde , um die Ausgabe in eine Datei zu verschieben und vor einer Server-Trennung zu schützen ):

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

    Mein Benutzer ist "postgres"

  3. nohup psql exampledbclone_01 < example-01.sql

Fusion27
quelle
15

In pgAdmin können Sie eine Sicherungskopie von Ihrer ursprünglichen Datenbank erstellen und dann einfach eine neue Datenbank erstellen und aus der soeben erstellten Sicherung wiederherstellen:

  1. Klicken Sie mit der rechten Maustaste auf die Quellendatenbank, Backup ... und sichern Sie sie in einer Datei.
  2. Klicken Sie mit der rechten Maustaste auf Neues Objekt, Neue Datenbank ... und benennen Sie das Ziel.
  3. Klicken Sie mit der rechten Maustaste auf die neue Datenbank, Wiederherstellen ... und wählen Sie Ihre Datei aus.
Isomorph
quelle
Ich habe verwandte Tabellen über Fremdschlüssel und das hat gut funktioniert.
Randall Blake
12

Was ist der richtige Weg, um die gesamte Datenbank (ihre Struktur und Daten) in eine neue in pgAdmin zu kopieren?

Antworten:

CREATE DATABASE newdb WITH TEMPLATE originaldb;

Ausprobiert und getestet.

Anirban Chakrabarti
quelle
3
Dies setzt voraus, dass originaldb nicht verwendet wird. Isomorphs Methode nicht.
Bradley
2
Die gleiche Antwort wurde fast drei Jahre vor Ihrer gegeben
Jason S
8

Aus der Dokumentation geht hervor , dass die Verwendung von createdboder CREATE DATABASEmit Vorlagen nicht empfohlen wird:

Obwohl es möglich ist, eine andere Datenbank als template1 zu kopieren, indem der Name als Vorlage angegeben wird, ist dies (noch) nicht als allgemeine Funktion zum Kopieren von Datenbanken gedacht. Die Hauptbeschränkung besteht darin, dass während des Kopierens keine anderen Sitzungen mit der Vorlagendatenbank verbunden werden können. CREATE DATABASE schlägt fehl, wenn beim Start eine andere Verbindung besteht. Andernfalls werden neue Verbindungen zur Vorlagendatenbank gesperrt, bis CREATE DATABASE abgeschlossen ist.

pg_dumpoder pg_dumpallist ein guter Weg, um die Datenbank und alle Daten zu kopieren. Wenn Sie eine GUI wie pgAdmin verwenden, werden diese Befehle hinter den Kulissen aufgerufen, wenn Sie einen Sicherungsbefehl ausführen. Das Kopieren in eine neue Datenbank erfolgt in zwei Phasen: Sichern und Wiederherstellen

pg_dumpallspeichert alle Datenbanken im PostgreSQL-Cluster. Der Nachteil dieses Ansatzes besteht darin, dass Sie eine möglicherweise sehr große Textdatei mit SQL erhalten, die zum Erstellen der Datenbank und zum Auffüllen der Daten erforderlich ist. Der Vorteil dieses Ansatzes besteht darin, dass Sie alle Rollen (Berechtigungen) für den Cluster kostenlos erhalten. Um alle Datenbanken zu sichern, führen Sie dies über das Superuser-Konto aus

pg_dumpall > db.out

und wiederherzustellen

psql -f db.out postgres

pg_dumphat einige Komprimierungsoptionen, die Ihnen viel kleinere Dateien geben. Ich habe eine Produktionsdatenbank, die ich zweimal täglich mit einem Cron-Job sichere

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

Wo compressist die Komprimierungsstufe (0 bis 9) und createsagtpg_dump an, Befehle zum Erstellen der Datenbank hinzuzufügen. Wiederherstellen (oder Verschieben in einen neuen Cluster) mithilfe von

pg_restore -d newdb db.dump

Dabei ist newdb der Name der Datenbank, die Sie verwenden möchten.

Andere Dinge, über die man nachdenken sollte

PostgreSQL verwendet ROLES zum Verwalten von Berechtigungen. Diese werden nicht von kopiert pg_dump. Außerdem haben wir uns nicht mit den Einstellungen in postgresql.conf und pg_hba.conf befasst (wenn Sie die Datenbank auf einen anderen Server verschieben). Sie müssen die conf-Einstellungen selbst herausfinden. Aber es gibt einen Trick, den ich gerade entdeckt habe, um Rollen zu sichern. Rollen werden auf Clusterebene verwaltet, und Sie können pg_dumpallmit dem --roles-onlyBefehlszeilenschalter die Sicherung nur der Rollen anfordern.

bfris
quelle
7

PostgreSQL 9.1.2:

$ CREATEDB new_db_name -T orig_db_name -O db_user;
Arta
quelle
3
Dies wird wahrscheinlich implementiert, da CREATE DATABASE newdb WITH TEMPLATE originaldb OWNER dbuser;die ursprüngliche Datenbank inaktiv sein muss (keine Verbindungen mit Schreibzugriff) und neue Verbindungen zur ursprünglichen Datenbank während des Kopiervorgangs verhindert werden. Wenn Sie damit zufrieden sind, funktioniert dies.
Mikko Rantalainen
Schönes Detail. Vielen Dank!
Arta
6

Für diejenigen, die noch interessiert sind, habe ich ein Bash-Skript entwickelt, das (mehr oder weniger) das tut, was der Autor wollte. Ich musste eine tägliche Kopie der Geschäftsdatenbank auf einem Produktionssystem erstellen, dieses Skript scheint den Trick zu tun. Denken Sie daran, die Werte für Datenbankname / Benutzer / pw zu ändern.

#!/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
quelle
5

So erstellen Sie einen Datenbankspeicherauszug

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

So setzen Sie den Datenbankspeicherauszug zurück

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
quelle
5

Hier ist der gesamte Vorgang zum Erstellen eines Kopierens über eine Datenbank nur mit der pgadmin4-GUI (über Sicherung und Wiederherstellung).

Postgres wird mit Pgadmin4 geliefert. Wenn Sie macOS verwenden, können Sie CMD+ drücken SPACEund eingeben pgadmin4, um es auszuführen. Dadurch wird eine Browser-Registerkarte in Chrome geöffnet.


Schritte zum Kopieren

1. Erstellen Sie das Backup

Klicken Sie dazu mit der rechten Maustaste auf die Datenbank -> "Backup"

Geben Sie hier die Bildbeschreibung ein

2. Geben Sie der Datei einen Namen.

Wie test12345. Klicken Sie auf Sichern. Dadurch wird ein Binärdateidump erstellt, der nicht in einem .sqlFormat vorliegt

Geben Sie hier die Bildbeschreibung ein

3. Sehen Sie, wo es heruntergeladen wurde

Unten rechts auf Ihrem Bildschirm sollte sich ein Popup befinden. Klicken Sie auf die Seite "Weitere Details", um zu sehen, wohin Ihr Backup heruntergeladen wurde

Geben Sie hier die Bildbeschreibung ein

4. Suchen Sie den Speicherort der heruntergeladenen Datei

In diesem Fall ist es /users/vincenttang

Geben Sie hier die Bildbeschreibung ein

5. Stellen Sie die Sicherung von pgadmin wieder her

Angenommen, Sie haben die Schritte 1 bis 4 korrekt ausgeführt, haben Sie eine Wiederherstellungs-Binärdatei. Es kann vorkommen, dass Ihr Mitarbeiter Ihre Wiederherstellungsdatei auf seinem lokalen Computer verwenden möchte. Habe gesagt, Person gehe zu pgadmin und stelle wieder her

Klicken Sie dazu mit der rechten Maustaste auf die Datenbank -> "Wiederherstellen"

Geben Sie hier die Bildbeschreibung ein

6. Wählen Sie den Dateisucher

Stellen Sie sicher, dass Sie den Speicherort der Datei manuell auswählen. Ziehen Sie eine Datei NICHT per Drag & Drop auf die Uploader-Felder in pgadmin. Weil Sie auf Fehlerberechtigungen stoßen. Suchen Sie stattdessen die gerade erstellte Datei:

Geben Sie hier die Bildbeschreibung ein

7. Suchen Sie die Datei

Möglicherweise müssen Sie den Filter unten rechts auf "Alle Dateien" ändern. Suchen Sie die Datei danach ab Schritt 4. Klicken Sie nun zur Bestätigung auf die untere rechte Schaltfläche "Auswählen"

Geben Sie hier die Bildbeschreibung ein

8. Stellen Sie die Datei wieder her

Diese Seite wird erneut mit dem Speicherort der ausgewählten Datei angezeigt. Fahren Sie fort und stellen Sie es wieder her

Geben Sie hier die Bildbeschreibung ein

9. Erfolg

Wenn alles in Ordnung ist, sollte unten rechts ein Indikator für eine erfolgreiche Wiederherstellung angezeigt werden. Sie können zu Ihren Tabellen navigieren, um festzustellen, ob die Daten für jede Tabelle ordnungsgemäß wiederhergestellt wurden.

10. Wenn es nicht erfolgreich war:

Sollte Schritt 9 fehlschlagen, löschen Sie Ihr altes öffentliches Schema in Ihrer Datenbank. Gehen Sie zu "Abfrage-Tool"

Geben Sie hier die Bildbeschreibung ein

Führen Sie diesen Codeblock aus:

DROP SCHEMA public CASCADE; CREATE SCHEMA public;

Geben Sie hier die Bildbeschreibung ein

Versuchen Sie nun die Schritte 5 bis 9 erneut, es sollte funktionieren

BEARBEITEN - Einige zusätzliche Hinweise. Aktualisieren Sie PGADMIN4, wenn beim Hochladen eine Fehlermeldung angezeigt wird, die der Wiederherstellung entspricht

Vincent Tang
quelle
3

Wenn die Datenbank offene Verbindungen hat, kann dieses Skript helfen. Ich verwende dies, um jede Nacht eine Testdatenbank aus einer Sicherung der Live-Produktionsdatenbank zu erstellen. Dies setzt voraus, dass Sie eine .SQL-Sicherungsdatei aus der Produktionsdatenbank haben (ich mache das in 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
quelle
1

Trennen Sie mit pgAdmin die Datenbank, die Sie als Vorlage verwenden möchten. Anschließend wählen Sie es als Vorlage zum Erstellen der neuen Datenbank aus. Dadurch wird vermieden, dass der bereits verwendete Fehler angezeigt wird.

immergrün2
quelle
0

Wenn Sie das gesamte Schema kopieren möchten, können Sie mit dem folgenden Befehl einen pg_dump erstellen:

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

Und wenn Sie diesen Speicherauszug importieren möchten, können Sie Folgendes verwenden:

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

Weitere Informationen zu Verbindungszeichenfolgen: https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING

Oder kombinieren Sie es einfach in einem Liner:

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
quelle
0
  1. Öffnen Sie das Hauptfenster in pgAdmin und öffnen Sie dann ein weiteres Fenster für Abfragetools
  2. In den Hauptfenstern von pgAdmin

Trennen Sie die Datenbank mit Vorlagen, die Sie als Vorlage verwenden möchten.

  1. Wechseln Sie zum Fenster "Abfrage-Tools"

Führen Sie 2 Abfragen wie folgt aus

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

(Die obige SQL-Anweisung beendet alle aktiven Sitzungen mit TemplateDB. Anschließend können Sie sie als Vorlage zum Erstellen der neuen TargetDB-Datenbank auswählen. Dadurch wird vermieden, dass der bereits verwendete Fehler angezeigt wird.)

CREATE DATABASE 'TargetDB'
  WITH TEMPLATE='TemplateDB'
       CONNECTION LIMIT=-1;
Titushui
quelle
-4

Versuche dies:

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
quelle