Postgres obsahuje pohyblivý horizont událostí, což je ve skutečnosti asi 2 miliardy transakcí před nebo za aktuálním ID transakce. Transakce až 2 miliardy před nebo více než 2 miliardy za aktuálním ID transakce jsou považovány za budoucí, a proto budou pro současné transakce neviditelné.
Postgres se této katastrofální ztrátě dat vyhýbá speciálním označením starých řádků, takže bez ohledu na to, kde jsou ve vztahu k aktuálnímu ID transakce, budou viditelné.
Zmrazení je tento proces označování starých živých n-tic (tj. databázových řádků), aby nebyly překročeny pohyblivým horizontem událostí, kvůli kterému by se jinak jevily jako v budoucnosti. To je v kontrastu s vysáváním, což je uvolnění prostoru spotřebovaného starými mrtvými n-ticemi, které již nejsou viditelné pro žádnou transakci.
Oba procesy jsou řízeny vakuem.
Existuje řada nastavení, která řídí způsob zmrazování.
Nejprve vacuum_freeze_min_age
určuje, zda bude nebo nebude n-tice zamrznuta, když se vakuum již dívá na stránku, aby zjistilo, zda obsahuje mrtvé n-tice, které lze vyčistit. N-tice starší než vacuum_freeze_min_age
v tomto případě zamrzne. Nastavení této nízké hodnoty znamená, že později bude potřeba méně práce, ale za možnou cenu zvýšeného úsilí jak v CPU, tak v IO nebo WAL aktivitě. Obecně pravděpodobně chcete, aby tato sada obsahovala transakce v hodnotě alespoň několika hodin. Řekněme, že očekáváte, že provedete až 2 000 transakcí za sekundu v trvalém tempu. 2000 TPS je 7,2 milionů transakcí za hodinu. Takže poměrně agresivní nastavení pro tento případ může být řekněme 20 m. Výchozí nastavení je 50 m. Podobně pro vacuum_multixact_freeze_min_age
. Mějte na paměti, že počítadla id transakce a multixid jsou nezávislá – musíte je sledovat oba.
Za druhé, existují vacuum_freeze_table_age
a vacuum_multixact_freeze_table_age
. Tato nastavení určují, kdy se automatické vysávání nepodívá pouze na stránky, které mohou mít mrtvé řádky, ale na jakoukoli stránku, která může mít neukotvené řádky. Výchozí nastavení pro tato nastavení je 150 m. Pokud jste snížili vacuum_freeze_min_age
dost, v mnoha případech bude mít toto agresivnější vakuum málo nebo žádnou práci. V každém případě tento proces není tak zaneprázdněný jako dříve, protože moderní verze Postgresu (9.6 a vyšší) uchovávají mapu stránek, kde jsou všechny n-tice zamrzlé, a navštěvují pouze ty stránky, které všechny zmrazené nejsou. To znamená, že toto již není úplné skenování tabulky.
Poslední je autovacuum_freeze_max_age
. Pokud při posledním úplném prohledání neukotvených řádků v tabulce došlo k více než tolika transakcím, autovakuum spustí vakuum proti obtékání stolu. Výchozí hodnota je 200 m. Podobně pro autovacuum_multixact_freeze_max_age
pro kterou je výchozí hodnota 400 m. To je něco, čemu se opravdu chcete vyhnout. Jsou dvě věci, které lze udělat. Za prvé, je velmi běžné zvýšit tato nastavení na něco jako 1 miliardu, abyste získali více prostoru, zejména na systémech, které jsou velkými spotřebiteli transakcí. Mohli byste toho dosáhnout více, ale chcete mít mezi nejstarší n-ticí a horizontem událostí dostatek transakčního prostoru. Za druhé, je důležité monitorovat vaše systémy a podniknout nápravná opatření, než se s tím nějaká databáze setká. Tato nápravná akce často zahrnuje ruční vysávání.
Jeden problém, který může nastat, je tam, kde máte DDL, které způsobí, že se normální (tj. ne anti-wraparound) autovakuum samo zruší. Pokud to nakonec uděláte dostatečně, dostanete vynucené vakuum proti obtékání a jakékoli DDL se pak za vakuovým procesem postaví do fronty, což zase zablokuje jakýkoli další DML. V této fázi je váš stůl prakticky nečitelný, dokud vakuum neskončí. To závisí na vzoru používání vaší databáze, ale není to jen teoretická možnost a nasazení Postgres a správci databází to musí vzít v úvahu.
Pro správu tohoto databázového klastru je zásadní monitorování vašeho databázového clusteru. Zejména musíte sledovat datfrozenxid
a datminmxid
každé databáze v klastru, a pokud jsou příliš staré, proveďte nápravná opatření, než bude vyžadováno vakuum proti obtékání. Často je problém s jednou nebo několika tabulkami v databázi. Které z nich jsou problémem, lze zjistit zkoumáním relfrozenxid
a relminmxid
z tabulek v databázi. age()
a mxid_age()
funkce jsou užitečné pro zjištění stáří id transakcí a čítačů multixid.
Zamrznutí není něco, čemu se můžete vyhnout, je to základní činnost údržby v Postgresu, kterou je třeba aktivně řídit.