База остановила запись, чтобы не потерять данные
Ошибка «database is not accepting commands to avoid wraparound data loss» в PostgreSQL: счётчик транзакций подошёл к пределу, база запретила запись. Как до этого не доводить и что делать, если уже случилось.
Что это значит
В PostgreSQL у каждой транзакции номер, и номера идут по кругу. Чтобы старые строки не перепутались с новыми, их периодически «замораживает» vacuum. Если заморозка долго не проходит, счётчик подходит к пределу. Сначала база пишет в журнал предупреждения must be vacuumed within N transactions, а у самого края перестаёт принимать запись совсем. Для Directum RX это полная остановка работы.
До такого доходит, когда autovacuum не успевает или ему мешают: долгие транзакции, забытые слоты репликации, подготовленные транзакции, выключенный autovacuum на больших таблицах.
Как проверить
- Насколько близко к пределу:
select datname, age(datfrozenxid) from pg_database order by 2 desc;
Тревожно от 1 миллиарда, предел около 2 миллиардов.
2. Что мешает заморозке: старые транзакции в pg_stat_activity, неактивные слоты в pg_replication_slots, записи в pg_prepared_xacts.
Что сделать
- Убрать то, что мешает: завершить долгие транзакции, удалить ненужные слоты репликации.
- Запустить заморозку для самых «старых» таблиц:
vacuum (freeze, verbose) <таблица>; - Если база уже не принимает запись, следовать указаниям в тексте ошибки. В свежих версиях достаточно
vacuumпод суперпользователем, однопользовательский режим не нужен. Это долгая операция, на неё нужно окно. - Поставить алерт на
age(datfrozenxid)с порогом задолго до предела.
Ошибка повторяется?
Запустите Диагностика: за полминуты он покажет состояние базы, брокера, поиска и сервера. С отчётом разберём причину за 30 минут бесплатного созвона.
Написать