Blog JSystems - uwalniamy wiedzę!
Blog JSystems - uwalniamy wiedzę!
PostgreSQL
Ostrzeżenie o transaction ID wraparound - jak zareagować
Transaction ID wraparound to jeden z niewielu problemów PostgreSQL, który potrafi zatrzymać całą bazę. Brzmi groźniej, niż jest w praktyce - o ile zareagujesz na ostrzeżenie i nie zignorujesz go. Tłumaczymy mechanizm i podajemy dokładną procedurę ratunkową.
Najpierw w logu widać ostrzeżenia typu WARNING: database "twoja_baza" must be vacuumed within 10000000 transactions. Jeśli je zignorujesz, komunikat staje się coraz bardziej naglący, aż baza wchodzi w tryb ochronny i przy próbie zapisu zwraca ERROR: database is not accepting commands to avoid wraparound data loss. Wtedy działają już tylko odczyty i operacje sprzątające.
Każda transakcja dostaje 32-bitowy identyfikator XID. Ponieważ to tylko około 4 miliardów wartości, przestrzeń XID jest traktowana jak okrąg: w danej chwili połowa wartości to przeszłość, a połowa przyszłość. Żeby stare wiersze nie zostały nagle uznane za pochodzące z przyszłości (co oznaczałoby ich zniknięcie), VACUUM zamraża je specjalnym znacznikiem, który mówi silnikowi, że wiersz jest widoczny dla wszystkich.
Jeśli autovacuum z jakiegoś powodu nie zamraża wierszy - bo jest wyłączony, bo długo trwająca transakcja albo porzucony slot replikacji trzyma stary horyzont, albo bo prace blokuje spuchnięta tabela - wiek najstarszego niezamrożonego XID rośnie. Gdy zbliża się do autovacuum_freeze_max_age, PostgreSQL wymusza agresywny autovacuum. Gdy mimo to podejdzie na krytyczną odległość, włącza tryb ochronny, żeby nie doszło do utraty danych.
SELECT datname, age(datfrozenxid) FROM pg_database ORDER BY age(datfrozenxid) DESC;. Wartość bliska 2 miliardom to stan alarmowy. Połącz się z tą bazą do dalszych kroków.SELECT relname, age(relfrozenxid) FROM pg_class WHERE relkind IN ('r','m','t') ORDER BY age(relfrozenxid) DESC LIMIT 20;. To one wymagają zamrożenia w pierwszej kolejności.SELECT pid, state, xact_start FROM pg_stat_activity ORDER BY xact_start; oraz SELECT slot_name, active FROM pg_replication_slots;. Zakończ wiszącą transakcję albo usuń nieużywany slot poleceniem SELECT pg_drop_replication_slot('nazwa');.VACUUM (FREEZE, VERBOSE) nazwa_tabeli;, a docelowo dla całej bazy vacuumdb --all --freeze --jobs=4 z linii poleceń.postgres --single -D /sciezka/do/pgdata twoja_baza, a następnie w konsoli wykonaj VACUUM FREEZE;. Po zakończeniu wróć do normalnego startu serwera.SHOW autovacuum; ma zwrócić on), monitoruj wiek XID w monitoringu i nie pozostawiaj otwartych transakcji ani martwych slotów replikacji na długo.Po zamrożeniu ponownie sprawdź wiek najstarszego XID: SELECT datname, age(datfrozenxid) FROM pg_database ORDER BY age(datfrozenxid) DESC; - wartości powinny wyraźnie spaść, do rzędu setek tysięcy zamiast miliardów. Ostrzeżenia w logu przestaną się pojawiać. Jeśli baza była w trybie ochronnym, po ponownym starcie przetestuj zwykły zapis, np. INSERT do tabeli testowej - powinien przejść bez błędu. Na koniec potwierdź w pg_class, że age(relfrozenxid) problematycznych tabel jest już niski.
Wróć do listy: 100 najczęstszych pytań i problemów z PostgreSQL

Sprawdź szkolenie: Administracja, replikacja i tuning baz danych PostgreSQL
To szkolenie może być dofinansowane z KFS lub BUR.
★★★★★Średnia ocena naszych szkoleń w Google: 5/5

Sprawdź szkolenie: Zaawansowana administracja PostgreSQL (HA, DR, monitoring, skalowanie)
To szkolenie może być dofinansowane z KFS lub BUR.
★★★★★Średnia ocena naszych szkoleń w Google: 5/5
Komentarze (0)
Brak komentarzy...