Bacula PostgreSQL Plugin - odtwarzanie bazy danych

Sporo czasu minęło od ostatniego opisu tworzonej przez zespół Inteos wtyczki do oprogramowania Bacula umożliwiającego pełne wykonywanie kopii zapasowych bazy danych PostgreSQL w trybie on-line z wykorzystaniem PITR. Dzisiaj na przykładach przedstawię w jaki sposób realizowana jest procedura odtworzenia środowiska. Bazuje ona na liście działań opisanych w oficjalnej dokumentacji do bazy danych.

Oficjalna lista działań jest dosyć długa i obejmuje 9 nie zawsze trywialnych kroków. Całość działań komplikuje dodatkowo architektura samego oprogramowania Bacula skoncentrowana na centralnej realizacji wszelkich zadań, w tym zadań odtwarzania danych. Ale przejdźmy do konkretów. W celu ułatwienia całej procedury i automatyzacji całego procesu uwzględniającego specyfikę pracy bazy PostgreSQL oraz środowiska Bacula powstało narzędzie pgsql-restore. Narzędzie korzysta z tego samego pliku konfiguracyjnego co pozostałe komponenty (pgsql-fd.so oraz pgsql-arch). Oczywiście możemy w całości zmodyfikować plik konfiguracyjny ze względu na nasze specyficzne potrzeby. Po uruchomieniu programu bez jakichkolwiek parametrów standardowo otrzymamy informację o wymaganej formie uruchomienia: 

Usage: pgsql-restore -c <config.file> [-v] [-t <recovery.time> |
    -x <recovery.xid> ] [-w <where>] restore

Znaczenie poszczególnych opcji:

  • -v - włącza gadatliwość całego procesu, w tym informacje otrzymywane z systemu backupowego i cały log procesu odzyskiwania w bazie danych; domyślnie opcja nie jest aktywna, więc standardowo poza komunikatem powitalnym nie wyświetlą się nam żadne informacje dotyczące przebiegu procesu odtwarzania
  • -t lub -x - opcje służące do wskazania bazie danych do którego momentu w czasie (-t) lub do którego numeru transakcji należy prowadzić odzyskiwanie; jeśli nie podamy żadnego z tych parametrów to odzyskiwanie będzie prowadzone do ostatniego dostępnego pliku WAL
  • -w - opcja służąca do wskazania nowej lokalizacji odtwarzanych plików bazodanowych clustra i przestrzeni tabel,  użyteczna podczas testowego odtwarzania bazy danych obok istniejącego środowiska produkcyjnego lub w przypadku migracji baz danych na całkowicie inne środowisko;
  • restore - opcja wskazująca że zainteresowani jesteśmy odtworzeniem środowiska backupowego;

Podczas procesu odtwarzania bazy danych program pgsql-restore komunikuje się z naszym środowiskiem backupowym wskazanym w pliku konfiguracyjnym pod następującymi parametrami:

DIRNAME = <director.name>
DIRHOST = <director.address>
DIRPORT = <director.service.port>
DIRPASSWD = <director.connection.password>

Parametry te definiują dedykowaną odtworzeniom konsolę sterującą opisaną w konfiguracji oprogramowania Bacula Director.

Przykładowa (i gadatliwa) sesja odtworzeniowa wygląda następująco:

$./pgsql-restore -v -c ../etc/pgsql.conf -x 650 restore
pgsql-restore:   =============================
pgsql-restore:  | PostgreSQL restore utility. |
pgsql-restore:  |     (c) 2010 by Inteos      |
pgsql-restore:   =============================
pgsql-restore:  Database RESTORE mode.
pgsql-restore:  CLIENT = ubuntu-client-test
pgsql-restore:  PGDATA = /var/lib/postgresql/8.4/test
pgsql-restore:  PGHOST = /var/run/postgresql
pgsql-restore:  PGPORT = 5433
pgsql-restore:  PITR until 650
pgsql-restore:  WHERE = < oryginal location >
pgsql-restore:  shutting down a runing PostgreSQL instance at PGDATA
pgsql-restore:  it is your last chance to interrupt recovery process ...
pgsql-restore:  3 ...
pgsql-restore:  2 ...
pgsql-restore:  1 ...
pgsql-restore:  OK, you choose wisely ...

Na początku program wypisuje informacje jakie ustalił na podstawie otrzymanych parametrów oraz z pliku konfiguracyjnego aby następnie rozpocząć standardową procedurę odtworzenia. Jeśli odtwarzamy bazę danych do lokalizacji w której aktualnie działa jakaś instancja bazy danych to program uprzejmie nas o tym poinformuje i da ostatnie trzy sekundy na zastanowienie się czy to jest to o co nam chodziło.

pgsql-restore:  server stopped
pgsql-restore:  shutdown complete
pgsql-restore:  copying unarchived wal logs
pgsql-restore:  remove old tablespaces
pgsql-restore:  remove old pgdata cluster

To chyba najbardziej niebezpieczna część całego procesu - kasowanie starych danych w celu posprzątania lokalizacji do której będziemy odtwarzali naszą bazę danych. Następnie zlecamy odtworzenie plików bazodanowych.

pgsql-restore:  connecting to director
pgsql-restore:  1000 OK: ubuntu-devel-dir Version: 5.1.7 (24 July 2010)
pgsql-restore:  looking for pgsql backups...
pgsql-restore:  pgsql backups found
pgsql-restore:  preparing for pgsql restore
pgsql-restore:  Bootstrap records written to /var/bacula/working/linux-devel-dir.restore.126.bsr
pgsql-restore:  The job will require the following
pgsql-restore:     Volume(s)                 Storage(s)                SD Device(s)
pgsql-restore:  ===========================================================================
pgsql-restore:     
pgsql-restore:      vol01                     File                      FileStorage              
pgsql-restore:  Volumes marked with "*" are online.
pgsql-restore:  692 files selected to be restored.
pgsql-restore:  Automatically selected Job: RestorePGSQL
pgsql-restore:  Job queued. JobId=300
pgsql-restore:  starting restore job: JobId=300
pgsql-restore:  waiting for job to finish
pgsql-restore:  datafiles restore done
pgsql-restore:  disconnecting from director

I uruchamiamy instancję bazodanową w trybie recovery.

pgsql-restore:  startup a PostgreSQL instance in Recovery Mode
pgsql-restore:  pg_ctl: another server might be running; trying to start server anyway
database system was interrupted; last known up at 2011-02-12 12:32:27 CET
starting archive recovery
restore_command = '/local/bacula/sbin/pgsql-restore -v -c /local/bacula/etc/pgsql.conf wal %f %p'
recovery_target_xid = 650

W naszym przypadku odtwarzamy bazę danych do podanego podczas uruchomienia numeru transakcji. Zamiast tego można podać specyfikację czasu. W obu przypadkach wymagane będzie dostarczenie silnikowi bazodanowemu zarchiwizowanych wcześniej plików logów WAL.

pgsql-restore:  WAL RESTORE mode.
pgsql-restore:  connecting to director
pgsql-restore:  1000 OK: ubuntu-devel-dir Version: 5.1.7 (24 July 2010)
pgsql-restore:  looking for pgsqlarch backups...
pgsql-restore:  pgsqlarch backups found
pgsql-restore:  preparing for wal restore: 0000001100000000000000B0.00000020.backup
pgsql-restore:  Automatically selected Client: ubuntu-devel-fd
pgsql-restore:  Bootstrap records written to /var/bacula/working/linux-devel-dir.restore.128.bsr
pgsql-restore:  The job will require the following
pgsql-restore:     Volume(s)                 Storage(s)                SD Device(s)
pgsql-restore:  ===========================================================================
pgsql-restore:     
pgsql-restore:      vol01                     File                      FileStorage
pgsql-restore:  Volumes marked with "*" are online.
pgsql-restore:  1 file selected to be restored.
pgsql-restore:  Automatically selected Job: RestorePGSQL
pgsql-restore:  Job queued. JobId=302
pgsql-restore:  starting restore job: JobId=302
pgsql-restore:  waiting for job to finish
pgsql-restore:  wal file restore done
pgsql-restore:  disconnecting from director
pgsql-restore:  WAL 0000001100000000000000B0.00000020.backup restore done.
pgsql-restore:  WAL RESTORE mode.
pgsql-restore:  WAL 0000001100000000000000B0 restore done.
restored log file "0000001100000000000000B0" from archive
automatic recovery in progress
redo starts at 0/B0000064, consistency will be reached at 0/B0000080
consistent recovery state reached

I tak wszystkie wymagane pliki logów aż baza danych osiągnie porządany przez administratora stan. Na zakończenie pozostaje tylko zamknięcie instancji bazy danych tak aby administrator mógł zweryfikować czy konfiguracja środowiska bazodanowego odpowiada potrzebom.

pgsql-restore:  RECOVERY COMPLETED!!!
received smart shutdown request
shutting down
database system is shut down
pgsql-restore:  Shutdown COMPLETED!!!
pgsql-restore:  server stopped
pgsql-restore:  Recovery complete

Proces zakończony z pełnym sukcesem. Dla czytelności powyższych logów wykasowałem wszystkie znaczniki czasu jakie drukowane są w każdej linii logu.