Траблшутинг автовакуума (Autovacuum) в PostgreSQL: борьба с Bloat и Wraparound
- Аномальный рост размера таблиц и индексов на диске (Bloat) при стабильном количестве строк.
- Деградация производительности последовательного сканирования (Seq Scan) из-за чтения «мертвых» строк (Dead Tuples).
- Критическое предупреждение в логах:
WARNING: database "postgres" must be vacuumed within X transactions(угроза Wraparound).
1. Поиск таблиц с наибольшим количеством мертвых кортежей
SELECT schemaname, relname,
n_live_tup, n_dead_tup,
round((n_dead_tup::float / nullif(n_dead_tup + n_live_tup, 0))::numeric * 100, 2) AS dead_tuple_ratio,
last_vacuum, last_autovacuum
FROM pg_stat_user_tables
WHERE (n_dead_tup + n_live_tup) > 10000
ORDER BY n_dead_tup DESC LIMIT 15;2. Глобальный тюнинг Autovacuum в postgresql.conf
# Увеличение количества параллельных воркеров вакуума
autovacuum_max_workers = 5
# Снижение задержки между раундами очистки
autovacuum_naptime = 15s
# Уменьшение порога срабатывания (по умолчанию 20% слишком много для больших таблиц)
autovacuum_vacuum_scale_factor = 0.05
autovacuum_analyze_scale_factor = 0.02
# Снятие ограничений по дисковому I/O (ускорение вакуума в 5-10 раз)
autovacuum_vacuum_cost_limit = 2000
autovacuum_vacuum_cost_delay = 2ms3. Индивидуальная настройка для сверхнагруженных таблиц
Для таблиц с миллионами апдейтов в час задайте агрессивные параметры:
ALTER TABLE orders SET (
autovacuum_vacuum_scale_factor = 0.01,
autovacuum_vacuum_threshold = 1000,
autovacuum_vacuum_cost_limit = 5000,
autovacuum_vacuum_cost_delay = 0
);4. Контроль риска Transaction ID Wraparound
SELECT datname, age(datfrozenxid),
2147483648 - age(datfrozenxid) AS tx_until_wraparound
FROM pg_database ORDER BY age(datfrozenxid) DESC; Частые вопросы (FAQ)
Почему стандартный autovacuum_vacuum_scale_factor = 0.2 не подходит для больших таблиц?
Для таблицы размером 100 млн строк очистка начнется только после накопления 20 млн мертвых строк, что приведет к гигабайтам мусора и тяжелому продолжительному I/O.
Что произойдет при исчерпании транзакций до Transaction ID Wraparound?
PostgreSQL принудительно перейдет в аварийный режим Read-Only и остановится для предотвращения перезаписи старых транзакций новыми идентификаторами.