Jednou ze zajímavých funkcí v PostgreSQL od verze 9.4 je schopnost řídit odstraňování souborů WAL pomocí replikačních slotů. Stinnou stránkou je, že replikační sloty mohou způsobit zaplnění disků starými WAL, což zabije hlavní produkční server. V tomto článku vysvětluji replikační sloty PostgreSQL a jak nová funkce v PostgreSQL 13 pomáhá tomuto problému předcházet.
Produkce WAL
Jak víte, WAL se vytváří pro změny databáze na primárním serveru:vkládání, aktualizace, a tak dále . Aktivnější databáze vytvoří více WAL — na velmi aktivním serveru může být každou minutu vyprodukováno mnoho gigabajtů WAL. WAL se zapisuje do souborů s názvy v rostoucím číselném pořadí a soubory mají vždy stejnou velikost (16 MB je výchozí a typické). Jakmile data v souboru již nejsou potřeba, lze tento soubor recyklovat , což znamená přejmenovat jej na pozici s vyšším číslem v sekvenci, aby jej bylo možné později vyplnit novými daty.
(Existují zvláštní situace, jako je nárůst aktivity, který vede k vytvoření dalších souborů; když později nárůst utichne, tyto nadbytečné soubory jsou odstraněny namísto recyklace.)
Protože veškerá činnost zápisu do databáze vytváří WAL, je důležité, aby byl k dispozici prostor na disku. Když je disk s WAL plný, server nebude schopen zpracovat nové transakce a může se zaseknout, nebo ještě hůř:může se úplně převrátit. To je tedy situace, které je třeba se všemi možnými prostředky vyhnout.
Replikační sloty
Replikace v PostgreSQL funguje na základě zpracování souborů WAL. Aby to fungovalo, musí být všechny soubory WAL dočasně dostupné, dokud nebudou zpracovány. Proto je potřeba mechanismus, který sdělí hlavní správě WAL, aby nerecyklovala nebo neodstraňovala soubory.
Zadejte replikační sloty. Sloty jsou mechanismem, který naznačuje, že toto záloha, kterou přijímáme, bude vyžadovat to WAL soubor a můžete jej prosím ještě nesmazat; nebo toto replika stále to nezpracovala WAL, můžete jej tedy prosím nechat chvíli o samotě.
Replikační sloty samy o sobě zabírají velmi málo místa na disku. Ukládají pouze malý kousek metadat, včetně ukazatele na pozici ve WAL. Ale data WAL, která chrání, jsou jiná věc:na vysoce aktivním serveru je lze měřit v gigabajtech nebo ještě horších.
Spotřeba WAL
Přivádění dat do fyzické repliky znamená kopírování dat WAL z jejího primárního serveru. Podobně logická replika potřebuje číst data WAL (a přenášet interpretovanou verzi do repliky). Pozice WAL, která se čte, je to, co slot sleduje. Jakmile replika nějakým způsobem zabezpečí data WAL, slot lze posunout; to sděluje správě WAL v primární části, že soubor WAL je poté k dispozici pro odstranění. To se děje nepřetržitě, když je replika aktivní, takže WAL na primárním serveru bude využívat stejné množství místa na disku nebo možná jen o něco více. V závislosti na podmínkách může být přijatelné i dvakrát tolik nebo desetkrát tolik.
Problém je v tom, že pokud replika zcela zemře a neobnoví se po dlouhou dobu; nebo je replika zničena a DBA zapomene odstranit replikační slot; nebo slot je zapomenutý zbytek nějakého experimentu; nebo je dokonce replika napájena přes pomalé síťové spojení, pak rezervovaná WAL poroste bez omezení. A to se stává tikající bombou.
Omezení velikosti slotu
Aby se tento problém vyřešil, Kyotaro Horiguchi pracoval od února 2017 na opravě PostgreSQL, aby omezil velikost WAL vyhrazenou slotem. Po velmi dlouhém procesu kontroly a přepracování jsem jej integroval do PostgreSQL 13, čímž jsem zlepšil správu vysoce dostupných PostgreSQL farem.
Hlavním principem je, že je lepší zabít repliku (nějakým způsobem znehodnotit její slot; více o tom níže), než zabít primární server, který tuto repliku napájí, a odstranit s ní veškerou produkci.
Způsob, jakým to funguje, je docela jednoduchý:nastavte max_slot_wal_keep_size
(dokumentace) v postgresql.conf na maximální množství místa na disku WAL, které si mohou replikační sloty vyhradit. Pokud slot dosáhne tohoto bodu a objeví se kontrolní bod, bude tento slot označen jako neplatný a některé soubory WAL mohou být smazány. Pokud slot aktivně používal walsender proces, bude tento proces signalizován tak, že skončí. Pokud walsender znovu spustí, zjistí, že potřebné soubory WAL tam již nebudou. Replika používající tento slot bude muset být znovu klonována.
Pokud max_slot_wal_keep_size
je nula, což je výchozí hodnota, pak neexistuje žádný limit. Nedoporučuji to, protože to vede k selhání, když sloty zaplní disk.
Monitorování stavu slotu
Součástí jsou také některé monitorovací funkce. Relevantní jsou dva sloupce v pg_replication_slots. Nejkritičtější je wal_status
. Pokud je tento sloupec reserved
, pak slot ukazuje na data v rámci max_wal_size
; pokud je extended
pak překročil max_wal_size
, ale je stále chráněn buď wal_keep_size
nebo max_slot_wal_keep_size
(včetně případů, kdy max_slot_wal_keep_size
je nula). Oba stavy jsou dobré a normální. Když však slot překročí limit, stane se nejprve unreserved
, což znamená, že je v bezprostředním nebezpečí, ale stále se může zotavit, pokud je dostatečně rychlý. Nakonec se stav změní na lost
když byly soubory WAL odstraněny a není možné žádné obnovení.
Druhý sloupec je safe_wal_size
:ukazuje počet bajtů WAL, které lze zapsat, než se tento slot dostane do nebezpečí odebrání souborů WAL. Doporučujeme bedlivě sledovat tento sloupec ve vašem monitorovacím systému a upozornit na požár, když se sníží. Nula nebo záporná hodnota znamená, že vaše replika bude mrtvá, jakmile nastane kontrolní bod:
SELECT slot_name, active, wal_status, safe_wal_size FROM pg_catalog.pg_replication_slots;
Věříme, že tato nová funkce usnadňuje a zpevňuje údržbu replik; doufejme, že kvůli těmto problémům již neuvidíme žádné další katastrofy s poklesem výroby.
(Poznámka:safe_wal_size
byl představen ve verzi 13beta3, takže si nezapomeňte prostudovat aktuální dokumentaci, jinak uvidíte min_safe_lsn
namísto. Ignorujte to.)
Děkuji
Zvláštní poděkování patří Kyotaro Horiguchimu za práci na řešení tohoto problému. Několik recenzentů se do toho dostalo hluboko, mezi nimiž bych rád poděkoval zejména Masahiko Sawada, Fujii Masao, Jehan-Guillaume de Rorthais a Amit Kapila (bez konkrétního pořadí).