Tworzenie kopii bazy danych w PostgreSQL

728

Jaki jest prawidłowy sposób skopiowania całej bazy danych (jej struktury i danych) do nowej w pgAdmin?

egaga
źródło

Odpowiedzi:

1120

Postgres pozwala na użycie dowolnej istniejącej bazy danych na serwerze jako szablonu podczas tworzenia nowej bazy danych. Nie jestem pewien, czy pgAdmin daje ci opcję w oknie dialogowym tworzenia bazy danych, ale jeśli nie, powinieneś być w stanie wykonać następujące czynności w oknie zapytania:

CREATE DATABASE newdb WITH TEMPLATE originaldb OWNER dbuser;

Mimo to możesz uzyskać:

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

Aby odłączyć wszystkich innych użytkowników od bazy danych, możesz użyć tego zapytania:

SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity 
WHERE pg_stat_activity.datname = 'originaldb' AND pid <> pg_backend_pid();
dzwon
źródło
68
Pamiętaj, że originaldb musi być bezczynne (bez transakcji zapisu), aby to działało.
synecdoche
62
w pgAdmin3, w okienku przeglądarki obiektów (po lewej), mogę wybrać Servers-> (mój serwer) -> Databases, kliknąć prawym przyciskiem myszy Bazy danych i wybrać „Nowa baza danych”. Jedną z opcji jest szablon, a SQL użyty do utworzenia bazy danych jest równoważny. Jest o wiele szybszy niż zrzut / przywracanie na tym samym serwerze.
jwhitlock
22
Wiem, że to stare pytanie / odpowiedź, ale wydaje mi się, że wymaga wyjaśnienia: kiedy @synecdoche mówi, że originaldb musi być bezczynne, oznacza to, że nie ma możliwości zapisu. „Kopiowanie” bazy danych w ten sposób nie blokuje originaldb. PostgreSQL uniemożliwia rozpoczęcie kopiowania tylko wtedy, gdy inni mają dostęp do originaldb - nie po rozpoczęciu kopiowania, więc możliwe jest, że inne połączenie może zmodyfikować bazę danych podczas „kopiowania”. IMHO, to może być najłatwiejsza odpowiedź, ale „najlepszym” byłoby użycie zrzutu / przywracania.
Josh
10
Właśnie to widziałem. @Josh: podczas kopiowania originaldb przez utworzenie bazy danych z szablonem postgresql nie pozwala na utworzenie nowego połączenia z nim, więc żadne zmiany nie są możliwe.
ceteras
4
Pamiętaj, że jeśli używasz pgAdmin i wykonujesz polecenie UTWÓRZ BAZĘ DANYCH ... SZABLON xxx w oknie poleceń SQL, musisz odłączyć się od bazy danych w głównym oknie pgAdmin, w przeciwnym razie pojawi się błąd związany z użytkownikami podłączonymi do bazy danych.
Jack RG
296

Wersja odpowiedzi Bell'a z wiersza poleceń :

createdb -O ownername -T originaldb newdb

Powinno to być uruchamiane z uprawnieniami administratora bazy danych, zwykle postgres.

zbyszek
źródło
5
To miłe polecenie, ALE dostaniesz, createdb: database creation failed: ERROR: source database "conf" is being accessed by other usersjeśli spróbujesz to zrobić na produkcyjnej bazie danych i zgodnie z oczekiwaniami nie chcesz go wyłączać, aby utworzyć kopię.
sorin
7
Tak, te same zastrzeżenia dotyczą tego polecenia, jak w przypadku jawnego wywołania CREATE DATABASE. Podobnie jak w komentarzach do powyższej odpowiedzi Bella, baza danych powinna być bezczynna.
zbyszek
108

Aby sklonować istniejącą bazę danych z postgres, możesz to zrobić

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

IT zabije wszystkie połączenia ze źródłową bazą danych, unikając błędu

ERROR:  source database "SOURCE_DB" is being accessed by other users
Brugolo
źródło
7
+1 za wzmiankę o skrypcie, aby uniknąć błędu dostępu
zastrasz
14
Na PostgreSQL 9.2 muszę wymienić procpidze pidto zadziałało
marxjohnson
75

W środowisku produkcyjnym, w którym oryginalna baza danych jest obciążona ruchem, po prostu używam:

pg_dump production-db | psql test-db
Tregoreg
źródło
8
Jednym z problemów, które znalazłem przy tej metodzie, jest to, że pg_dump wstrzyma swoją transakcję do czasu zakończenia przywracania do nowej bazy danych, nawet jeśli pg_dump faktycznie zakończy zrzut. W niektórych przypadkach może to powodować problemy z blokowaniem (na przykład, jeśli na źródłowej bazie danych uruchomiona zostanie instrukcja DDL).
Chris Butler,
3
Plus jeden za nieużywanie tymczasowych plików pośrednich.
Ardee Aram
To było również moje rozwiązanie. Wczoraj działało, teraz naruszane są losowe ograniczenia unikalne. Uwaga: upuszczam całą tabelę do db db odbiornika.
gunzapper
1
@AlexanderMills pg_dump -s? postgresql.org/docs/current/static/app-pgdump.html
Tregoreg
1
Zakłada się, że test-db istnieje. W przeciwnym razie utwórz nową $ createdb newdb
bazę danych za
50

Nie wiem o pgAdmin, ale pgdumpdaje zrzut bazy danych w SQL. Musisz tylko utworzyć bazę danych o tej samej nazwie i zrobić

psql mydatabase < my dump

aby przywrócić wszystkie tabele i ich dane oraz wszystkie uprawnienia dostępu.

TrayMan
źródło
Dzięki, musiałem stworzyć zrzut z innego serwera, i wygląda na to, że to pomaga: postgresql.org/docs/8.3/interactive/…
egaga
19
Możesz to zrobić, pg_dump -U postgres sourcedb | psql -U postgres newdbchociaż skuteczność tej techniki może być wątpliwa (ponieważ prawdopodobnie kończysz się przełączaniem kontekstu między odczytami i zapisami)
Frank Farmer
1
Możesz nawet uzyskać zrzut ze zdalnego komputera za pośrednictwem ssh: ssh dbserver pg_dump DBNAME | psql NEWDB... lub pg_dump DBNAME | ssh otherserver pgsql NEWDB ... Uprawnienia i uwierzytelnianie oczywiście muszą być obsługiwane bez względu na to, jak chcesz je obsłużyć.
ghoti
23

Po pierwsze, sudojako użytkownik bazy danych:

sudo su postgres

Przejdź do wiersza polecenia PostgreSQL:

psql

Utwórz nową bazę danych, nadaj uprawnienia i wyjdź:

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

Skopiuj strukturę i dane ze starej bazy danych do nowej:

pg_dump old_database_name | psql new_database_name
Mathieu Rodic
źródło
jak upewnić się, że wszystko jest w porządku, nawet jeśli wystąpiły jakieś błędy (problem z siecią)? Jak sprawdzić, czy po migracji dwie bazy danych są takie same?
BAE
Błędy powinny być wyświetlane w terminalu przy każdym napotkaniu. Dwie bazy danych powinny być takie same po operacji. Nie wiem jednak, jak to sprawdzić ...
Mathieu Rodic
2
Działa jak urok, zrobiłem to, gdy baza danych była w produkcji.
BioRod
To wydaje się działać dobrze; jednak dwie bazy danych mają inny rozmiar dysku za pośrednictwem \l+. Dlaczego różnica wielkości?
kosgeinsky
@kosgeinsky, na które szeroko odpowiedziano tutaj: dba.stackexchange.com/a/102089/39386
Mathieu Rodic
18

Połączyłem to podejście z przykładami z góry. Pracuję na serwerze „pod obciążeniem” i dostałem błąd, gdy spróbowałem podejść z @zbyszek. Ja też szukałem rozwiązania „tylko z linii poleceń”.

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

Oto, co zadziałało dla mnie ( Polecenia poprzedzone nohupprzeniesieniem danych wyjściowych do pliku i zabezpieczeniem przed rozłączeniem serwera ):

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

    mój użytkownik to „postgres”

  3. nohup psql exampledbclone_01 < example-01.sql

fusion27
źródło
15

W pgAdmin możesz wykonać kopię zapasową z oryginalnej bazy danych, a następnie po prostu utworzyć nową bazę danych i przywrócić z utworzonej kopii zapasowej:

  1. Kliknij prawym przyciskiem myszy źródłową bazę danych, kopię zapasową ... i zrzuć do pliku.
  2. Kliknij prawym przyciskiem myszy, Nowy obiekt, Nowa baza danych ... i nazwij cel.
  3. Kliknij nową bazę danych prawym przyciskiem myszy, Przywróć ... i wybierz plik.
Izomorf
źródło
Mam powiązane tabele za pomocą kluczy obcych i to działało dobrze.
Randall Blake
12

Jaki jest prawidłowy sposób skopiowania całej bazy danych (jej struktury i danych) do nowej w pgAdmin?

Odpowiedź:

CREATE DATABASE newdb WITH TEMPLATE originaldb;

Wypróbowany i przetestowany.

Anirban Chakrabarti
źródło
3
To wymaga, aby originaldb nie był używany. Metoda Isomorpha nie.
Bradley,
2
Ta sama odpowiedź została udzielona prawie trzy lata przed twoją
Jason S
8

Z dokumentacji nie zaleca się używania createdblub używania CREATE DATABASEszablonów:

Chociaż możliwe jest skopiowanie bazy danych innej niż template1 poprzez określenie jej nazwy jako szablonu, nie jest to (jeszcze) przeznaczone do ogólnego zastosowania narzędzie „KOPIUJ BAZĘ DANYCH”. Głównym ograniczeniem jest to, że podczas kopiowania nie można połączyć żadnych innych sesji z bazą danych szablonów. UTWÓRZ BAZA DANYCH zakończy się niepowodzeniem, jeśli jakiekolwiek inne połączenie istnieje podczas uruchamiania; w przeciwnym razie nowe połączenia z bazą danych szablonów będą blokowane do momentu ukończenia operacji UTWÓRZ BAZA DANYCH.

pg_dumplub pg_dumpalljest dobrym sposobem na skopiowanie bazy danych i wszystkich danych. Jeśli używasz GUI, takiego jak pgAdmin, te polecenia są wywoływane za kulisami podczas wykonywania polecenia tworzenia kopii zapasowej. Kopiowanie do nowej bazy danych odbywa się w dwóch etapach: Kopia zapasowa i Przywracanie

pg_dumpallzapisuje wszystkie bazy danych w klastrze PostgreSQL. Wadą tego podejścia jest to, że powstaje potencjalnie bardzo duży plik tekstowy pełen kodu SQL wymagany do utworzenia bazy danych i zapełnienia danych. Zaletą tego podejścia jest to, że otrzymujesz wszystkie role (uprawnienia) dla klastra za darmo. Aby zrzucić wszystkie bazy danych, zrób to z konta administratora

pg_dumpall > db.out

i przywrócić

psql -f db.out postgres

pg_dumpma kilka opcji kompresji, które dają znacznie mniejsze pliki. Mam produkcyjną bazę danych, której kopię zapasową tworzę dwa razy dziennie przy użyciu zadania cron

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

gdzie compressjest poziomem kompresji (od 0 do 9) i createkaże pg_dumpdodawać polecenia, aby utworzyć bazę danych. Przywróć (lub przenieś do nowego klastra) za pomocą

pg_restore -d newdb db.dump

gdzie newdb to nazwa bazy danych, której chcesz użyć.

Inne rzeczy do przemyślenia

PostgreSQL używa ROLES do zarządzania uprawnieniami. Nie są one kopiowane przez pg_dump. Ponadto nie zajmowaliśmy się ustawieniami w postgresql.conf i pg_hba.conf (jeśli przenosisz bazę danych na inny serwer). Musisz samodzielnie skonfigurować ustawienia conf. Ale właśnie odkryłem sztuczkę polegającą na tworzeniu kopii zapasowych ról. Role są zarządzane na poziomie klastra i można poprosić pg_dumpallo wykonanie kopii zapasowej tylko ról za pomocą --roles-onlyprzełącznika wiersza polecenia.

bfris
źródło
7

PostgreSQL 9.1.2:

$ CREATEDB new_db_name -T orig_db_name -O db_user;
Arta
źródło
3
Prawdopodobnie jest to zaimplementowane, ponieważ CREATE DATABASE newdb WITH TEMPLATE originaldb OWNER dbuser;w rezultacie wymaga, aby oryginalna baza danych była bezczynna (brak połączeń z dostępem do zapisu), a wszelkie nowe połączenia z oryginalną bazą danych były blokowane podczas kopiowania. Jeśli jesteś z tego zadowolony, to działa.
Mikko Rantalainen
Niezły szczegół. Dziękuję Ci!
Arta,
6

Dla tych, którzy są nadal zainteresowani, opracowałem skrypt bash, który robi (mniej więcej) to, czego chciał autor. Musiałem wykonać codzienną kopię biznesowej bazy danych w systemie produkcyjnym, ten skrypt wydaje się załatwić sprawę. Pamiętaj o zmianie wartości nazwy bazy danych / użytkownika / 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
źródło
5

Aby utworzyć zrzut bazy danych

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

Aby ponownie zrzucić zrzut bazy danych

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
źródło
5

Oto cały proces tworzenia kopii w bazie danych przy użyciu tylko GUI pgadmin4 (poprzez tworzenie kopii zapasowych i przywracanie)

Postgres jest dostarczany z Pgadmin4. Jeśli używasz systemu macOS, możesz nacisnąć CMD+ SPACEi wpisać, pgadmin4aby go uruchomić. Spowoduje to otwarcie karty przeglądarki w chrome.


Kroki do kopiowania

1. Utwórz kopię zapasową

Zrób to, klikając bazę danych prawym przyciskiem myszy -> „kopia zapasowa”

wprowadź opis zdjęcia tutaj

2. Nadaj plikowi nazwę.

Jak test12345. Kliknij kopię zapasową. Tworzy to zrzut pliku binarnego, nie ma .sqlformatu

wprowadź opis zdjęcia tutaj

3. Zobacz, gdzie został pobrany

W prawym dolnym rogu ekranu powinno być wyskakujące okienko. Kliknij stronę „więcej szczegółów”, aby zobaczyć, gdzie została pobrana kopia zapasowa

wprowadź opis zdjęcia tutaj

4. Znajdź lokalizację pobranego pliku

W tym przypadku tak jest /users/vincenttang

wprowadź opis zdjęcia tutaj

5. Przywróć kopię zapasową z pgadmin

Zakładając, że poprawnie wykonałeś kroki od 1 do 4, będziesz mieć plik binarny przywracania. Może się zdarzyć, że Twój współpracownik będzie chciał użyć pliku przywracania na swoim komputerze lokalnym. Powiedz tej osobie, aby poszła do pgadmin i przywróciła

Zrób to, klikając bazę danych prawym przyciskiem myszy -> „przywróć”

wprowadź opis zdjęcia tutaj

6. Wybierz wyszukiwarkę plików

Pamiętaj, aby ręcznie wybrać lokalizację pliku, NIE przeciągaj i nie upuszczaj pliku na pola programu przesyłającego w pgadmin. Ponieważ napotkasz uprawnienia do błędu. Zamiast tego znajdź właśnie utworzony plik:

wprowadź opis zdjęcia tutaj

7. Znajdź wspomniany plik

Może być konieczna zmiana filtra u dołu na „Wszystkie pliki”. Znajdź plik od kroku 4. Teraz naciśnij prawy przycisk „Wybierz”, aby potwierdzić

wprowadź opis zdjęcia tutaj

8. Przywróć wspomniany plik

Ponownie zobaczysz tę stronę z wybraną lokalizacją pliku. Śmiało i przywróć go

wprowadź opis zdjęcia tutaj

9. Sukces

Jeśli wszystko jest w porządku, w prawym dolnym rogu powinien wyskoczyć wskaźnik pokazujący udane przywracanie. Możesz przejść do swoich tabel, aby sprawdzić, czy dane zostały przywrócone dla każdej tabeli.

10. Jeśli to się nie powiedzie:

Jeśli krok 9 nie powiedzie się, spróbuj usunąć stary schemat publiczny z bazy danych. Przejdź do „Narzędzia do wysyłania zapytań”

wprowadź opis zdjęcia tutaj

Wykonaj ten blok kodu:

DROP SCHEMA public CASCADE; CREATE SCHEMA public;

wprowadź opis zdjęcia tutaj

Teraz spróbuj ponownie wykonać kroki od 5 do 9, powinno się to udać

EDYCJA - Kilka dodatkowych uwag. Zaktualizuj PGADMIN4, jeśli podczas przesyłania wystąpi błąd z czymś podobnym do „nieobsługiwanej wersji archiwizatora nagłówka 1.14” podczas przywracania

Vincent Tang
źródło
3

Jeśli baza danych ma otwarte połączenia, ten skrypt może pomóc. Używam tego do tworzenia testowej bazy danych z kopii zapasowej bazy danych produkcji na żywo każdej nocy. Zakłada się, że masz plik kopii zapasowej .SQL z produkcyjnej bazy danych (robię to w 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
źródło
1

Za pomocą pgAdmin odłącz bazę danych, której chcesz użyć jako szablonu. Następnie wybierasz go jako szablon do utworzenia nowej bazy danych, co pozwala uniknąć błędu już używanego.

evergreener2
źródło
0

Jeśli chcesz skopiować cały schemat, możesz wykonać zrzut pg za pomocą następującego polecenia:

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

A kiedy chcesz zaimportować ten zrzut, możesz użyć:

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

Więcej informacji na temat parametrów połączenia: https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING

Lub po prostu łącząc go w jedną wkładkę:

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
źródło
0
  1. Otwórz okno główne w pgAdmin, a następnie otwórz kolejne okno narzędzi do wysyłania zapytań
  2. W głównych oknach w pgAdmin,

Odłącz „szablonową” bazę danych, której chcesz użyć jako szablonu.

  1. Przejdź do okna narzędzi do wysyłania zapytań

Uruchom 2 zapytania, jak poniżej

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

(Powyższa instrukcja SQL zakończy wszystkie aktywne sesje z TemplateDB, a następnie możesz ją teraz wybrać jako szablon do utworzenia nowej bazy danych TargetDB, co pozwoli uniknąć błędu już używanego).

CREATE DATABASE 'TargetDB'
  WITH TEMPLATE='TemplateDB'
       CONNECTION LIMIT=-1;
titushui
źródło
-4

Spróbuj tego:

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

użytkownik3108031
źródło