Postgres zawiera ruchomy horyzont zdarzeń, który oznacza około 2 miliardy transakcji przed lub za bieżącym identyfikatorem transakcji. Transakcje do 2 miliardów przed lub ponad 2 miliardy za bieżącym identyfikatorem transakcji są uważane za przyszłe, a zatem będą niewidoczne dla bieżących transakcji.
Postgres unika tej katastrofalnej utraty danych, specjalnie oznaczając stare wiersze, aby były widoczne bez względu na to, gdzie się znajdują w odniesieniu do bieżącego identyfikatora transakcji.
Zamrażanie to proces oznaczania starych żywych krotek (tj. wierszy bazy danych), aby nie zostały przejechane przez przesuwający się horyzont zdarzeń, który w przeciwnym razie sprawiłby, że wyglądały na przyszłe. Jest to przeciwieństwo odkurzania, które polega na zwalnianiu miejsca zajmowanego przez stare martwe krotki, które nie są już widoczne dla żadnej transakcji.
Oba procesy są zarządzane przez próżnię.
Istnieje wiele ustawień regulujących sposób zamrażania.
Najpierw vacuum_freeze_min_age
określa, czy krotka zostanie zamrożona, gdy próżnia już patrzy na stronę, aby sprawdzić, czy ma martwe krotki, które można wyczyścić. Krotki starsze niż vacuum_freeze_min_age
w tym przypadku zostanie zamrożone. Ustawienie tego niskiego oznacza, że będzie mniej pracy do wykonania później, ale możliwym kosztem dodatkowego wysiłku zarówno w aktywności CPU, jak i IO lub WAL. Generalnie prawdopodobnie chcesz, aby ten zestaw zawierał co najmniej kilka godzin transakcji. Załóżmy, że spodziewasz się wykonać do 2000 transakcji na sekundę jako stałą stawkę. 2000 TPS to 7,2 mln transakcji na godzinę. Tak więc dość agresywnym ustawieniem w tym przypadku może być powiedzmy 20m. Domyślne ustawienie to 50m. Podobnie dla vacuum_multixact_freeze_min_age
. Zwróć uwagę, że liczniki transaction_id i multixid są niezależne – musisz śledzić oba z nich.
Po drugie, istnieje vacuum_freeze_table_age
i vacuum_multixact_freeze_table_age
. Te ustawienia określają, kiedy autovacuum nie tylko będzie patrzeć na strony, które mogą mieć martwe wiersze, ale na każdą stronę, która może mieć odmrożone wiersze. Wartości domyślne dla tych ustawień to 150m. Jeśli zmniejszyłeś vacuum_freeze_min_age
wystarczy, że w wielu przypadkach ta bardziej agresywna próżnia będzie miała niewiele pracy lub nie będzie miała jej wcale. W każdym razie ten proces nie jest tak zajęty jak kiedyś, ponieważ współczesne wersje Postgresa (9.6 i nowsze) przechowują mapę stron, na których wszystkie krotki są zamrożone, i odwiedzają tylko te strony, które nie są zamrożone. Oznacza to, że nie jest to już pełne skanowanie tabeli.
Ostatni to autovacuum_freeze_max_age
. Jeśli ostatnim razem, gdy stół został całkowicie przeskanowany pod kątem niezamrożonych wierszy, było więcej niż tyle transakcji temu, funkcja autovacuum uruchomi próżnię zapobiegającą zawijaniu na stole. Wartość domyślna to 200m. Podobnie dla autovacuum_multixact_freeze_max_age
dla których domyślna wartość to 400m. To jest coś, czego naprawdę chcesz uniknąć. Można zrobić dwie rzeczy. Po pierwsze, bardzo często zwiększa się te ustawienia do około 1 miliarda, aby zapewnić sobie większy zapas, zwłaszcza w systemach, które są dużymi konsumentami transakcji. Możesz zrobić więcej, ale chcesz mieć dużo miejsca na transakcje między najstarszą krotką a horyzontem zdarzeń. Po drugie, ważne jest, aby monitorować swoje systemy i podejmować działania naprawcze, zanim wejdą w to bazy danych. To działanie naprawcze często obejmuje ręczne odkurzanie.
Jednym z problemów, który może wystąpić, jest sytuacja, w której masz DDL, który powoduje normalne (tj. nie zapobiegające zawijaniu) automatyczne odkurzanie, które samo się anuluje. Jeśli zrobisz to wystarczająco dużo, w końcu dostaniesz wymuszone podciśnienie zapobiegające zawijaniu, a każdy DDL następnie ustawi się w kolejce za procesem podciśnienia, co z kolei zablokuje dalsze DML. Na tym etapie Twój stół jest praktycznie nieczytelny, dopóki próżnia się nie skończy. Zależy to od wzorca użytkowania Twojej bazy danych, ale nie jest to tylko teoretyczna możliwość, a wdrożenia Postgres i administratorzy baz danych muszą to brać pod uwagę.
Monitorowanie klastra bazy danych ma kluczowe znaczenie dla zarządzania tym. W szczególności musisz monitorować datfrozenxid
i datminmxid
każdej bazy danych w klastrze, a jeśli te staną się zbyt stare, podejmij działania naprawcze, zanim wymagane będzie podciśnienie zapobiegające zawijaniu. Często problem dotyczy jednej lub kilku tabel w bazie danych. Które z nich są problemem, można wykryć, sprawdzając relfrozenxid
i relminmxid
tabel w bazie danych. age()
i mxid_age()
funkcje są przydatne do wykrywania, odpowiednio, wieku identyfikatorów transakcji i liczników multixid.
Zamrażanie nie jest czymś, czego można uniknąć, jest to niezbędna czynność konserwacyjna w Postgresie, którą należy aktywnie zarządzać.