Blog JSystems - uwalniamy wiedzę!

Szukaj
Z tego artykułu dowiesz się:
  • czym się różni backup logiczny od fizycznego, jakie są plusy i minusy obu,
  • w jaki sposób wykonać backup logiczny wybranej bazy danych,
  • w jaki sposób wykonać backup logiczny wybranej tabeli,
  • w jaki sposób wykonać backup logiczny ze zdalnego hosta,
  • w jaki sposób wykonać backup logiczny całego klastra,
  • w jaki sposób odtwarzać backupy logiczne,
  • w jaki sposób wykonać skompresowany backup logiczny,
  • w jaki sposób odtwarzać skompresowane backupy logiczne,
  • w jaki sposób skonfigurować plik .pgpass byśmy nie byli proszeni o hasło przy każdym wywołaniu backupu - - przydatne zwłaszcza przy skryptowaniu backupów.

Backup za pomocą pg_dump lub pg_dumpall jest backupem logicznym, czyli zawierającym struktury danych (jak tabele czy indeksy) i dane, ale nie struktury fizyczne. Jest to zawsze zrzut do pliku SQL lub jego binarnego (często skompresowanego) formatu. Zwykłe pliki SQL - mogą następnie być konsumowane przez choćby "psql", ich binarna postać przez pg_restore. Taki backup pozwala robić kopie zapasowe wszystkich lub wybranych baz danych, a nawet wybranych tabel. Możemy też potraktować taki plik backupu jak zwykły plik tekstowy, wyciąć i odtworzyć to, co nam jest potrzebne wybiórczo. Zarówno pg_dump jak i pg_dumpall są często wykorzystywane do kopiowania danych pomiędzy serwerami. Backup za pomocą pg_dump - czy pg_dumpall pozwoli nam - na tworzenie kopii zapasowych, które można przywrócić tylko do momentu ich wykonania. Ponadto taki backup nie zawiera danych o konfiguracji klastra zawartych w plikach takich jak "postgresql.conf" czy "pg_hba.conf". Różnica pomiędzy pg_dump a pg_dumpall jest taka, że pg_dump pozwala zbackupować wybrane bazy czy elementy, a pg_dumpall zawsze backupuje wszystkie bazy. Ponadto pg_dump nie zrzuca do skryptu instrukcji tworzenia użytkowników, a pg_dumpall to robi. Kopie zapasowe wykonywane za pomocą pg_dump i pg_dumpall są konsystentne i takie pozostaną nawet w przypadku, gdyby ktoś modyfikował dane w trakcie wykonywania kopii zapasowej. Dzieje się tak, ponieważ kopia ta wykonywana jest w trybie serializable. Oznacza to, - że zmiany wykonane po rozpoczęciu wykonywania backupu nie będą w nim ujęte.

Doświadczenie z wykonywaniem kopii zapasowych zaczniemy od stworzenia sobie tabeli.

create table do_zrzutu(x integer,y text);
insert into do_zrzutu(x) select generate_series(1,1000000);
update do_zrzutu set y='element numer '||x;

Sprawdzamy, - czy tabela istnieje i czy zawiera dodane dane:

select count(*) from do_zrzutu;

Zwróćmy uwagę na wielkość tabeli w bazie źródłowe - 91MB. Odniosę się do tego nieco później.

Aby wykonać kopię zapasową wybranej bazy za pomocą "pg_dump", wywołujemy (przełącznik -d stosujemy, by wskazać bazę, którą zamierzamy backupować - w tym przypadku postgres. Możemy ten przełącznik pominąć, ponieważ jeśli jesteśmy zalogowani jako użytkownik systemowy ";postgres", - to pg_dump będzie się domyślnie łączył jako użytkownik o takiej nazwie.):

pg_dump -d postgres > /tmp/postgres.sql

To spowoduje utworzenie pliku SQL z instrukcjami tworzącymi i zapełniającymi struktury danych. Możemy do tego pliku zajrzeć za pomocą VI czy NANO i zobaczyć mniej więcej coś takiego:

Jak widać, są to zwykłe komendy SQL. Można odtworzyć ten plik choćby za pomocą "psql". Żeby to przetestować, logujemy się do psql, tworzymy docelową bazę danych i ładujemy do niej dane z pliku zrzuconego przez pg_dump:

psql -c "create database kopia";
psql -d kopia -f /tmp/postgres.sql

W zależności od liczby danych ten proces może trwać bardzo długo, w końcu trzeba wykonać wszystkie te komendy SQL zawarte w pliku.

Po zakończeniu ładowania łączymy się do docelowej bazy i sprawdzamy jej zawartość:

Ktoś dociekliwy mógłby zauważyć, że co prawda liczba wierszy jest taka sama w obu bazach, ale wielkość się różni. Dlaczego? Ponieważ w przypadku tej źródłowej tabeli wykonywaliśmy "update", - w związku z czym powstało wiele martwych wierszy. Druga baza miała dane ładowane od razu w docelowym stanie, więc takie martwe wiersze nie powstawały. Jak to zweryfikować? Najprościej zalogować się do bazy źródłowej, wykonać "vacuum full" na tej tabeli i porównać wielkości:

Zrzucić możemy również kilka baz na jeden - raz. Tu na potrzeby przykładu wcześniej tworzymy nową bazę:

psql -c "create database nowa"
pg_dump -d postgres -d nowa > /tmp/dwie_bazy.sql

Zrzucić możemy również wybraną tabelę:

pg_dump -t do_zrzutu > /tmp/do_zrzutu.sql

Nie podajemy tutaj, do jakiej bazy się łączymy, więc domyślnie łączymy się do bazy "postgres" dlatego, że w systemie jesteśmy zalogowani jako użytkownik "postgres". Domyślnie też łączymy się do bazy o nazwie takiej jak użytkownik. Z tego wynika, że niejawnie łączymy się jako użytkownik "postgres" do bazy "postgres". Możemy tu stosować przełączniki takie jak przy psql tj. -d (baza), -h (host), -U (użytkownik) -p (port) etc. w dowolnej kolejności:

pg_dump -h localhost -d nowa -t do_zrzutu -U postgres -p 5432 > /tmp/dump.sql

Możemy też zrzucić zbiór tabel- stosujemy po prostu -t wielokrotnie. Najpierw jednak tworzymy - tabelę, by pg_dump nie rzucił błędem o braku drugiej tabeli:

psql -c "create table druga(x integer)"
pg_dump -t do_zrzutu -t druga > /tmp/obie_tabele.sql

Obie tabele znajdą się we wspólnym pliku SQL. Fragment zawartości pliku "/tmp/obie_tabele.sql":

Narzędziem pg_dumpall możemy - stworzyć kopię zapasową wszystkich baz w klastrze:

pg_dumpall > /tmp/all.sql

Ponieważ pliki tak tworzonej kopii zapasowej są w rzeczywistości plikiem tekstowym, ładnie się kompresują. Warto stosować kompresję, by nasze kopie zapasowe zajmowały mniej miejsca. Domyślnie dostaniemy kopię zapasową bez kompresji. Zrzucamy i sprawdzamy wielkość kopii zapasowej bazy postgres:

pg_dumpall > /tmp/all.sql

Ponieważ pliki tak utworzonej kopii zapasowej są w rzeczywistości plikiem tekstowym, ładnie się kompresują. Warto stosować kompresję, - by nasze kopie zapasowe zajmowały mniej miejsca. Domyślnie dostaniemy kopię zapasową bez kompresji. Zrzucamy w wersji skompresowanej i sprawdzamy wielkość kopii zapasowej bazy postgres utworzonej wcześniej bez kompresji oraz kopii zapasowej w wersji skompresowanej:

pg_dump > /tmp/postgres.tar -Fc -Z9
ls -latr --block-size=M /tmp

Wersja bez kompresji zajmowała 28MB, z kompresją 6MB. Możemy posłużyć się przełącznikiem "-Fc" powodującym customowy tryb formatu. Po nim musi nastąpić wskazanie poziomu kompresji za pomocą "-ZX". Dostępne są wartości od -Z0 do -Z9 o wzrastającym stopniu kompresji. - Wybraliśmy najwyższą możliwą kompresję.

Odtwarzanie pliku stworzonego w ten sposób trzeba będzie wykonać za pomocą pg_restore, ponieważ nie jest to standardowy format backupu (tu dodatkowo tworzymy - nową bazę, do której wczytamy ten backup):

psql -c "create database z_tara"
pg_restore -d z_tara < /tmp/postgres.tar

Zaglądamy do nowej bazy, obie tabele są:

pg_dumpall zwykle będziemy uruchamiali z którymś z przełączników: -g, -s, -r. Oznaczają one kolejno

  • -g tylko obiekty globalne - użytkownicy, przestrzenie tabel etc - bez baz danych, tabel, indeksów i podobnych
  • -s tylko struktury danych - obiekty globalne i struktury danych bez danych - czyli np puste tabelki
  • -r tylko - role (użytkownicy), bez obiektów, baz danych czy przestrzeni tabel

Zarówno pg_dump jak i pg_dumpall pozwalają na wykonanie kopii zapasowej "po sieci" ze zdalnego serwera:

pg_dump -h 13.81.53.1 > /tmp/po_sieci.sql

Musimy jedynie pamiętać o odpowiednim wpisie w pg_hba.conf po stronie serwera docelowego i przeładowaniu konfiguracji po ewentualnej zmianie tego pliku.

W przypadku serwera zdalnego (lokalnie dostępny jest trust w pg_hba.conf) podczas wykonywania takiej kopii zapasowej zostaniemy poproszeni o hasło. Jeśli chcemy zautomatyzować tworzenie backupu np. za pomocą CRONa, pojawi się problem, ponieważ nie mamy wtedy jak wstukać hasła. Istnieje i na to metoda. Wystarczy stworzyć w katalogu domowym użytkownika postgres plik ".pgpass" i umieścić w nim niezbędne dane. - Zaczniemy od przejścia do właściwego katalogu i utworzenia pliku. Nadajemy mu też koniecznie chmod 600:

cd ~
touch .pgpass
chmod 600 .pgpass
nano .pgpass

We wnętrzu tego pliku musimy wprowadzić dane wg systematyki:

ip_hosta_którego_robimy_backup:port:baza_danych:użytkownik:hasło

W tym przypadku zawartość tego pliku będzie wyglądała tak:

13.81.53.1:5432:postgres:postgres:super_tajne_haslo

Przy kolejnym wywołaniu pg_dump nie zostaniemy już poproszeni o hasło.

Jeśli zamierzamy po prostu skopiować dane z jednego serwera na inny możemy posłużyć się taką konstrukcją (tu dodatkowo tworzymy bazę docelową):

psql -c "create database z_innego_hosta"
pg_dump -h 13.81.53.1 -d postgres - | psql -h 13.81.53.1 -d - z_innego_hosta

Tu został wykorzystany ten sam adres IP, ale oczywiście mogą to być różne hosty. Można osobno zrzucić bazę źródłową do pliku, a następnie osobno ją wczytać za pomocą psql. W takiej sytuacji po drodze tworzony byłby (być może bardzo duży) plik, co mogłoby znacząco wydłużyć cały proces. My za pomocą "|" przekierowujemy strumień danych do psql, zamiast kierować dane do pliku. Sprawdzam jeszcze, logując się do docelowej bazy, czy dane zostały skopiowane:

Komentarze (0)

Musisz być zalogowany by móc dodać komentarz. Zaloguj się przez Google

Brak komentarzy...