Autovacuum launcher

Autovacuum launcher — это фоновый процесс PostgreSQL, который не выполняет очистку напрямую, а запускает рабочие процессы autovacuum worker, когда базе данных требуется автоматическая очистка (vacuum) или анализ (analyze).

Он — «диспетчер» автоматической очистки, а не исполнитель

Autovacuum launcher — это фоновый процесс PostgreSQL, который не выполняет очистку напрямую, а запускает рабочие процессы autovacuum worker, когда базе данных требуется автоматическая очистка (vacuum) или анализ (analyze).

Autovacuum launcher — это «надзиратель» MVCC, который:

  • Следит за состоянием таблиц,
  • Запускает уборку (VACUUM) и анализ (ANALYZE) по мере необходимости,
  • Предотвращает раздувание данных и деградацию планов запросов.

MVCC, Vacuum - Механизм пометки строк как удаленные

Без него PostgreSQL со временем остановился бы из-за:

  • Переполнения диска (bloat),
  • Невозможности найти свободное место на страницах,
  • Плохих планов из-за устаревшей статистики.

Формула запуска VACUUM:

мёртвые_строки ≥ autovacuum_vacuum_threshold + autovacuum_vacuum_scale_factor × общее_число_строк

Главная задача Autovacuum launcher

Мониторить состояние таблиц в фоне и запускать autovacuum worker для тех из них, где накопилось достаточно «мёртвых» строк или изменилась статистика.

«мёртвыe» строки - В PostgreSQL при выполнении Delete строка не удаляется сразу а помечается как удаленная, в ней меняются некоторые поля метаданных. Это ускоряет работу, не приходится в текущий момент совершать множество дополнительных операций:

  • Строка остаётся на диске, в том же 8 КБ-блоке
  • Не требуется сдвигать другие строки, чтобы «заткнуть дыру».
  • Не нужно обновлять указатели в индексах, ведущие к этой строке.

Без MVCC: удаление → фрагментация → необходимость VACUUM FULL или REINDEX.

  • Страница не перезаписывается, не вызывается fsync().
  • Нет необходимости обновлять free space map (FSM) сразу.

Без него MVCC в PostgreSQL привёл бы к неограниченному раздуванию (bloat) и устаревшей статистике, что убивает производительность.

Как это работает (по шагам)

  1. При старте кластера postmaster запускает один процесс autovacuum launcher.
  2. Launcher периодически (раз в autovacuum_naptime, по умолчанию — 1 минута) сканирует все таблицы во всех базах данных.
  3. Для каждой таблицы он проверяет:
    • Сколько мёртвых строк накопилось (по данным из pg_stat_user_tables.n_dead_tup),
    • Насколько устарела статистика (по числу изменений и pg_statistic).
  4. Если таблица превысила пороги (на основе autovacuum_vacuum_threshold, autovacuum_vacuum_scale_factor и аналогов для ANALYZE) →
    запускает autovacuum worker для этой таблицы.
  5. Worker выполняет:
    • VACUUM — удаляет мёртвые строки, обновляет visibility map,
    • и/или ANALYZE — собирает статистику для планировщика.

Ключевые параметры

ПараметрПо умолчаниюРоль
autovacuumonВключена ли автоматическая очистка
autovacuum_naptime1minКак часто launcher проверяет таблицы
autovacuum_vacuum_threshold50Минимум «мёртвых» строк для запуска VACUUM
autovacuum_vacuum_scale_factor0.2Доля от общего числа строк (например, 20%)
autovacuum_max_workers3Макс. число одновременных worker’ов
autovacuum_vacuum_cost_delay20msЗадержка для ограничения I/O (на worker’а)

Важные нюансы

  • Один launcher — на весь кластер, но он обслуживает все базы данных.
  • Несколько worker’ов могут работать одновременно (до autovacuum_max_workers).
  • Launcher не запускает worker для таблиц, где autovacuum_enabled = false.
  • Если все worker’ы заняты — launcher ожидает, пока один освободится.
  • При очень высокой нагрузке на запись launcher может не успевать → bloat растёт → нужно настраивать пороги или увеличивать число worker’ов.

Мониторинг

-- Текущие autovacuum-процессы
SELECT pid, query FROM pg_stat_activity
WHERE query LIKE 'autovacuum%';
 
-- Статистика по таблицам
SELECT schemaname, tablename,
       n_tup_ins, n_tup_upd, n_tup_del,
       n_dead_tup,
       last_autovacuum, last_autoanalyze
FROM pg_stat_user_tables
WHERE n_dead_tup > 0;

Autovacuum worker ^psql-autovacuum-worker

Autovacuum worker — это фоновый процесс PostgreSQL, который выполняет реальную работу по очистке (VACUUM) и анализу (ANALYZE) таблиц, когда это необходимо для поддержания производительности и целостности MVCC.

Он запускается Autovacuum launcher’ом и работает непосредственно с данными, в отличие от launcher’а, который только принимает решения.

  • Это отдельный ОС-процесс, запускаемый postmaster по запросу Autovacuum launcher’а.
  • В ps aux вы увидите:
postgres: autovacuum: VACUUM public.orders
postgres: autovacuum: ANALYZE public.users

Может быть до autovacuum_max_workers одновременных worker’ов (по умолчанию — 3).

Главные задачи Autovacuum worker

1. Очистка мёртвых строк (VACUUM)

  • В PostgreSQL при UPDATE/DELETE старые версии строк не удаляются сразу (MVCC).
  • Со временем это приводит к bloat — таблица раздувается, замедляется сканирование.
  • Worker находит мёртвые строки, которые больше не нужны ни одной активной транзакции, и:
    • Помечает их пространство как свободное для повторного использования,
    • Обновляет Visibility Map (файл _vm) — чтобы при последующих сканированиях можно было пропускать целые страницы.

Это не уменьшает физический размер файла таблицы (только VACUUM FULL это делает), но освобождает место внутри файла.

2. Сбор статистики (ANALYZE)

  • Планировщик PostgreSQL строит планы запросов на основе статистики (pg_statistic).
  • Если статистика устарела — планы становятся неоптимальными.
  • Worker:
    • Сканирует часть таблицы,
    • Собирает данные о распределении значений,
    • Обновляет pg_statistic.

Это критично для сложных условий (WHERE, JOIN, GROUP BY).

3. Предотвращение wraparound транзакций

  • XID в PostgreSQL — 32-битный, циклический (от 0 до ~4 млрд).
  • Если не обновлять frozen XID, старые транзакции могут «завернуться» и стать будущими → катастрофа.
  • Worker «замораживает» очень старые строки (устанавливает xmin = FrozenTransactionId), чтобы они были видны всегда.
  • Это обязательная операция, иначе PostgreSQL останавливает все записи, чтобы избежать потери данных.

При приближении к autovacuum_freeze_max_age (по умолчанию 200 млн XID) autovacuum усиливается принудительно.


Как выбирается таблица для обработки?

Worker получает от launcher’а конкретную таблицу и тип операции (VACUUM, ANALYZE или оба).
Решение принимается на основе:

УсловиеДействие
n_dead_tup ≥ thresholdЗапуск VACUUM
n_mod_since_analyze ≥ thresholdЗапуск ANALYZE
age(datfrozenxid) ≥ autovacuum_freeze_max_ageПринудительный VACUUM с freeze

Пороги:
threshold = autovacuum_vacuum_threshold + autovacuum_vacuum_scale_factor * n_tup

блокировки берёт Autovacuum worker?

  • ShareUpdateExclusiveLock на таблицу:
    • ✅ Совместима с SELECT, INSERT, UPDATE, DELETE,
    • ❌ Конфликтует с ALTER, DROP, VACUUM FULL, CREATE INDEX.

Важные нюансы

  • Worker работает «вежливо»:
    Использует cost-based throttling (autovacuum_vacuum_cost_delay), чтобы не нагружать диск.
  • Не блокирует DML, но может замедляться из-за активности пользователей (например, при долгих транзакциях).
  • Не может очистить строку, если есть долгая транзакция, для которой она ещё видима → bloat растёт.
  • При работе с очень большими таблицами может выполняться часами.

Мониторинг

-- Текущие autovacuum-процессы
SELECT pid, datname, relname, phase, heap_blks_scanned, heap_blks_total
FROM pg_stat_progress_vacuum;
 
-- История очистки
SELECT schemaname, tablename,
       last_autovacuum, last_autoanalyze,
       n_dead_tup, n_tup_upd, n_tup_del
FROM pg_stat_user_tables
ORDER BY n_dead_tup DESC;