linuxlab.io
Учебники▾
  • Линукс и сети
    Файловая система, процессы, TCP/IP, BGP и OSPF
    →
  • Terraform и IaC
    HCL, state, plan/apply на sandbox LocalStack
    →
  • Git и GitHub
    Объектная модель, plumbing, ветвление, GitHub Actions
    →
Все учебники →
ЦеныО платформеВойтиСоздать аккаунт
/
Intro
Lessons
Footer
linuxlab-УчебникиЦеныО платформеКонфиденциальность и куки
Copyright © 2026 LinuxLab. Все права защищены.
linuxlab.io
Учебники▾
  • Линукс и сети
    Файловая система, процессы, TCP/IP, BGP и OSPF
    →
  • Terraform и IaC
    HCL, state, plan/apply на sandbox LocalStack
    →
  • Git и GitHub
    Объектная модель, plumbing, ветвление, GitHub Actions
    →
Все учебники →
ЦеныО платформеВойтиСоздать аккаунт
/
  • Введение
  • Главы
  • How it worksскоро
  • Уроки
  • База знаний
  • Собеседование
home/postgres/kb/Vacuum, freeze, wraparound/transaction-horizon

kb/vacuum ── Vacuum, freeze, wraparound ── intermediate

Горизонт транзакции

Горизонт - минимум backend_xmin по всем активным транзакциям. Версию строки можно убрать, только если она стала мёртвой раньше горизонта. Одна долгая или idle-in-transaction транзакция отодвигает горизонт назад и запрещает уборку мусора во всей базе.

view as markdownaka: xmin-horizon, vacuum-horizon, oldest-xmin

Что это

В любой момент в базе есть активные транзакции. У каждой - снимок (см. snapshot), который может потребовать версии строк, существовавшие на момент её старта. Поэтому VACUUM не имеет права удалять версию, если хоть одна живая транзакция могла бы её увидеть.

Граница, отделяющая «точно никому не нужно» от «ещё может понадобиться», и называется горизонтом. Технически это минимум backend_xmin по всем активным бэкендам. Внутри VACUUM это число зовётся removable cutoff (OldestXmin).

Правило удаления

Версия удаляема, если её xmax (см. xmin-xmax) закоммичен и строго старше горизонта. Если xmax новее или равен горизонту - версия остаётся, даже если фактически уже мёртвая. В отчёте VACUUM VERBOSE такие версии попадают в строку N dead but not yet removable.

Кто держит горизонт

Горизонт двигается вперёд только когда завершаются старые транзакции. Удержать его может:

  • долгий аналитический запрос или транзакция REPEATABLE READ;
  • забытая транзакция в состоянии idle in transaction;
  • подготовленная (PREPARE TRANSACTION) и не завершённая транзакция;
  • долгий запрос на реплике при включённом hot_standby_feedback (см. hot-standby-feedback) - он отодвигает горизонт мастера.

Диагностика

sql
SELECT pid, state, backend_xmin,
       now() - xact_start AS xact_age, query
FROM pg_stat_activity
WHERE state IN ('active', 'idle in transaction')
ORDER BY xact_start;

Самая старая транзакция вверху - вероятный держатель горизонта. Защита от забытых транзакций - idle_in_transaction_session_timeout.

Почему это важно

Застрявший горизонт - причина половины проблем с раздуванием. VACUUM отрабатывает, но почти ничего не удаляет (см. vacuum), мусор копится, а заодно не двигается граница заморозки (см. freeze). Поэтому при жалобах на bloat первым делом ищут длинную транзакцию.

§ команды

bash
SELECT pid, state, backend_xmin FROM pg_stat_activity ORDER BY backend_xmin;

Кто держит горизонт: смотрим самый старый backend_xmin

bash
SET idle_in_transaction_session_timeout = '5min';

Автоматически прибивать транзакции, висящие без дела

§ см. также

  • vacuumVACUUM и removable cutoffVACUUM удаляет мёртвые версии из таблицы и индексов, обновляет Free Space Map и Visibility Map, продвигает горизонт заморозки. Удаляет только версии старше removable cutoff. Обычный VACUUM не уменьшает файл - это делает VACUUM FULL под эксклюзивной блокировкой.
  • freezeЗаморозка и relfrozenxidЗаморозка помечает старую версию как видимую всем безусловно (бит HEAP_XMIN_FROZEN), выводя её из круговых сравнений и защищая от wraparound. relfrozenxid - граница заморозки таблицы; age(relfrozenxid) показывает её возраст в транзакциях.
  • autovacuumAutovacuum: пороги и bloatAutovacuum чистит таблицу, когда мёртвых версий накопится больше порога threshold + scale_factor × reltuples (50 и 0.2 по умолчанию). scale_factor 0.2 плохо масштабируется на большие таблицы, поэтому горячим задают индивидуальные пороги. autovacuum=off ведёт к bloat и wraparound.
  • snapshotСнимок данных (snapshot)Снимок - это не копия данных, а три числа: xmin, xmax и список активных xid между ними. Плюс правило, как по ним решать видимость версии. По снимку транзакция отделяет «прошлое» (зафиксировано до неё) от «настоящего» (идёт прямо сейчас) и «будущего» (ещё не начато). Дёшево по памяти, дорого по числу соединений.
  • hot-standby-feedbackhot_standby_feedback и vacuum мастераДлинный запрос на standby читает старые версии строк. Если primary их уже почистил vacuum'ом, standby обязан либо отменить запрос (конфликт восстановления), либо отстать. hot_standby_feedback = on говорит primary не удалять то, что ещё нужно standby - ценой роста мусора на primary.
Footer
linuxlab-
Copyright © 2026 LinuxLab. Все права защищены.
Учебники
Цены
О платформе
Конфиденциальность и куки