Několik způsobů zálohování databáze

PostgreSQL logo Lukáš Zapletal u minulého článku o upgrade PostgreSQL na novou major verzi navrhl téma na nový článek. Zajímají ho způsoby zálohování. Mě také :-). Já se necítím být odborníkem na toto téma, tento článek je tedy spíše otevření diskuse. Popíšu několik způsobů „jak to dělám já“ a proč a rád se dozvím vaše metody a názory na jednotlivé způsoby a který je váš preferovaný.

Obnovení zálohy

Na počátku každého zálohování stoji zamyšlení nad tím, co, jak a kdy chci obnovit. Pokud chci obnovit běh celého serveru, nemá smysl se zabývat metodami uložení stavu jednotlivých aplikací, ale opravdu zálohou a obnovou celého serveru. A naopak, pokud pracuji s daty a v průběhu práce je mohu pokazit, je dobré si udělat lokální jednorázovou zálohu právě a jen těch dat.

Dumpy databáze

„Klasický“ pg_dump

Nejjednodušší a okamžitě použitelná je metoda uložení databáze do souboru. To většinou může provést přímo uživatel (protože už k oné databází má přístup). Tedy ono klasické

pg_dump jmeno_db > jmeno_souboru

Do souboru se uloží sekvence SQL příkazů.

Se souborem se dá potom pracovat jako s kterýmkoliv jiným textovým souborem, lze jej podle potřeby editovat apod.

Obnovení je snadné pomocí standardního klienta:

psql jmeno_db < jmeno_souboru

Podobně jej lze načíst i přímo v „interaktivním režimu“ v psql klientovi. Může se také hodit import dat uzavřít do transakce, v případě většího počtu záznamů to bude mnohonásobně rychlejší než import v autocommit režimu (velmi záleží na konkrétním typu dat).

jmeno_db$ BEGIN;
jmeno_db$ \i jmeno_souboru
jmeno_db$ COMMIT;

A pod.

Speciální formáty pg_dump -F

Příkaz pg_dump umí uložit data i do jiných formátů. V některých případech je vytvoření dumpu mnohem rychlejší. Osobně často používám pg_dump -Fc, který je velmi rychlý a také komprimovaný. Výsledný dump je tak současně i malý.

Pro obnovení databáze uložených do speciálních formátů už si nevystačíme s klasickým psql klientem, potřebujeme program pg_restore.

Více o speciálních formátech se dočtete v manuálových stránkách programu pg_dump.

Dumpy celého clusteru

Klasický pg_dump uloží pouze jednu databázi. Může jej volat obyčejný uživatel. Pro uložení stavu celého clusteru slouží příkaz pg_dumpall. Volá jej databázový superuživatel. Tento příkaz do souboru uloží všechny databáze a další systémové objekty, například uživatele a jejich hesla. AFAIK v PostgreSQL neexistuje jiný způsob (kromě přímého dotazu do systémového katalogu), jak uložit a obnovit uživatele, skupiny a hesla.

Tento dump opět obnovíme pomocí psql klienta, opět jako superuživatel.

Výhody a nevýhody dumpů

Zálohy pomocí dumpů jsou bezesporu nejuniverzálnější a nejméně problémové. Může je vytvářet a obnovovat uživatel i s omezenými právy.

Problémy s klasickými dumpy nastávájí v případě velkých databází. Například pokud máme požadavek držet zálohu 1 měsíc nazpět a záloha se bude pořizovat každý den (což je docela málo, zálohy určitých systémů se provádějí mnohem častěji), budeme na záložním serveru potřebovat 30x velikost zálohy. Pokud má databáze velikost například 30GB, potřebujeme mít na záloze vyhrazeno přibližně cca asi něco kolem 1TB místa. Pro jednu jedinou databázi.

Produkční systémy bývají jednak objemnější, a také nároky na zálohování jsou přísnější. Máme-li například data o velikosti 2TB a požadavek na zálohování každé 4 hodiny a historii zálohy 3 měsíce (zcela reálné zadání) potřebovali bychom mít na zálohovacím serveru vyhrazeno přibližně 1PB místa. Dámy a pánové, nechci se vás dotknout – kdo z vás to má? ;-)

Nehledě na to, že žádnou metodou dumpů bychom těch 2TB v tomto čase ani neodzálohovali.

Online backup (PITR)

Metoda zálohování PITR o které jsem u už také psal problém s velikostí řeší. Zálohování probíhá průběžně během běžné práce databázového serveru. WAL logy, které databázový server stejně vytváří se jen navíc kopírují na zálohovací server.

Obnovení této zálohy potom skýtá mnoho možností a to včetně obnovení až k číslu konkrétní transkakce. Můžeme tedy databázi obnovit k času až několik sekund před haváríí (srovnejte si to s dumpy, které se vytvářejí jednou za čas).

Obrovská nevýhoda je, že tímto způsobem lze obnovit pouze celý cluster. Zatímco u dumpů si můžeme obnovit konkrétní databázi a ostatní jsou nedotčené, tak pomocí PITR obnovujeme vždy stav celého databázového serveru.

Což u velkých systémů nevadí, tam často bývá jedna databáze per server, ovšem máme-li databází stovky, je nereálné výtvářet pro každou z nich vlastní databázový server a zařizovat ještě PITR.

Opravdu bych si velmi přál, aby někdy v budoucnu v Postgresu existovala možnost mít PITR per DB.

Zálohování celých virtuálních serverů

Někdy vyvstane potřeba obnovit běh celého serveru a nikoliv jen jedné konkrétní aplikace (v tématu článku se jedná o PostgreSQL, ale tohle se týká obecně čehokoliv).

Některé virtualizační technologie umožňují dělat inkrementální zálohy virtuálních disků. Mají přehled o tom, které bloky se od minula změnily a při zálohování tak zálohují jen je. Výhodou jsou velmi malé inkrementy jednotlivých záloh, zálohy je možné pořizovat tak často, jak je potřeba.

Nevýhodou je, že nelze obnovit data konkrétní aplikace nebo snad konkrétní databáze (jedné z mnoha, které běží na databázovém virtualizovaném serveru).

V praxi

se potom používají kombinace těchto metod.

Malé databáze vytvářené například pro vývojáře se zálohují pomocí dumpů. Právě proto, že v tomto procesu je potřeba obnovit konkrétní databázi z konkrétního času zálohy. Dumpy jsou malé, je tedy možné ukládat historii záloh (a to navíc nepříliš dlouhou).

V produkčním prostředí netřeba obnovovat konkrétní databáze příliš často. Proto se zálohují celé virtuální servery dle potřeby jejich kompletního obnovení po havárii. A pokud občas nastane potřeba obnovit nějakou konkrétní databázi, tak se hold obnoví celý server bokem a konkrétní db se vytáhne. Není to rychlé, ale je to reálné. Pokud se to neděje vícekrát než 5x do roka, tak je to i snesitelné.

Ve speciálních případech, kdy je na jednom serveru jen jedna databáze (a to často hodně velká), je nejlepším řešením metoda PITR. Zálohování je kontiuální a nijak nezatěžuje zálohovaný stroj, obnovení je velmi rychlé a navíc je možné data obnovit velmi blízko k času problému. Nevýhodou je, že tato metoda obnovuje pouze celý cluster, jinak by byla zcela ultimátní.

Co jsem v praxi nezkoušel

Velmi zajímavá by mohla být metoda snapshotů systému souborů (například BTRFS nebo ZFS) na kterém je databáze umístěná. Snapshoty je možné pořizovat libovolně často a navíc je možné je libovolně mazat (na rozdíl od většiny metod inkrementálních záloh).

Problém je, že běh databázového serveru na COW filesystémech není zrovna rychlý (z celkem jasných důvodů), takže výhody takovéhoto řešení by nejspíš spolehlivě zabila pomalost normálního běhu databáze.

Co se také občas dělá

A to už hodně závisí na návrhu aplikace právě za tímto účelem. Pokud je aplikace navržena tak, že data do databáze pouze zapisuje (a nikdy nemodifikuje staré záznamy), tak je možnost ukládat rozdílové soubory obsahující přírůstky jen od poslední rozdílové zálohy. Tohle se používá u opravdu, ale opravdu velkých dat, která nelze zálohovat jako celek. Ovšem systém tak musí být od počátku navržen.

Závěrem

Tohle je několik mých postřehů z praxe a povídání o tom, jak to dělám já. Velmi rád si přečtu vaše názory a vaše metody z praxe, protože některé věci nemám stále uspokojivě vyřešené:

  • Dumpy jsou skvělé (do určité velikosti), ale velmi špatně se ukládají. Bylo by dobré mít nějakou metodu inkremetnálního ukládání dumpů.
  • PITR je vynikající pro zálohování celého clusteru, ale poněkud nevhodný pro obnovení konkrétní DB. Existuje podobná metoda, která tohle umí řešit?
  • Má někdo zkušenosti s během produkční databáze na systému souborů využívající COW? (Na linuxu se jedná patrně pouze o BTRFS.)

 

Příspěvek byl publikován v rubrice Databáze, PostgreSQL. Můžete si uložit jeho odkaz mezi své oblíbené záložky.

4 komentáře: Několik způsobů zálohování databáze

  1. Milan Kozák napsal:

    Ja pouzivam ve zkratce:
    /etc/init.d/postgresql stop
    sync
    lvcreate -s -n lv_backup vg1/lv_root -L 100G
    service postgresql start
    mount /dev/vg1/lv_backup /mnt/backup/
    rsync -avxHAXSP –numeric-ids /mnt/backup/ root@server:/kam/
    umount /mnt/backup
    lvremove vg1/lv_backup

    Zastaveni PostgreSQL a udelani snapshotu trva radove vterinu, rsyncovat se pak da libovolne dlouho. Delam tak kazdy den soucasne dve databaze – kazda o velikosti cca 600GB a neni s tim zadny problem (mohl by byt kdyby se menilo hodne dat nalinkovanych na snaphot, ale to se u me nedeje). Vyhody i nevyhody jsou pomerne jasne.

  2. OSukup napsal:

    btrfs umoznouje atribut NOCOW u souboru :)

    • Heron napsal:

      JJ.

      Ale asi to nebude potřeba. Dělal jsem nedávno lehké testy PG na BTRFS a je tam obrovský výkonnostní nárůst. Takže moje informace o pomalosti běhu na cow je tímto, zdá se, již minulostí. U mě teď PG na BTRFS šlape jak hodinky. :-)

  3. Pingback: PgBarman | Heronovo

Komentáře nejsou povoleny.