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/MVCC и видимость/clog-hint-bits

kb/mvcc ── MVCC и видимость ── intermediate

clog и подсказки фиксации (hint bits)

Зафиксирована транзакция или откатилась, хранит clog (каталог pg_xact) - всего два бита на транзакцию. Чтобы не дёргать clog при каждом чтении строки, результат проверки кэшируется в самой строке подсказками фиксации в t_infomask. Первый прочитавший строку ставит подсказку - и тем самым пачкает страницу, даже если это был обычный SELECT.

view as markdownaka: hint-bits, pg-xact

Поля xmin и xmax (см. xmin-xmax) - это просто номера транзакций. По ним нельзя узнать, чем транзакция кончилась: коммитом или откатом. Этот факт хранится отдельно.

clog: два бита на транзакцию

Статус каждой транзакции лежит в clog - каталоге pg_xact/ внутри PGDATA. На транзакцию приходится всего два бита:

БитыСтатус
в процессеещё идёт
committedзафиксирована
abortedоткатилась
sub-committedподтранзакция (промежуточно)

Два бита на транзакцию - это очень компактно: статусы миллионов транзакций умещаются в мегабайты, а горячая часть кэшируется в памяти. Когда правило видимости спрашивает «а xmin этой версии точно закоммитился?», ответ ищется именно в clog.

Подсказки фиксации: не спрашивать дважды

Лезть в clog на каждую строку при каждом чтении было бы дорого. Поэтому результат проверки кэшируется прямо в строке - подсказками фиксации (hint bits) в поле t_infomask (см. tuple-header):

Флаги HEAP_XMIN_COMMITTED / HEAP_XMIN_INVALID и парные для xmax означают «создатель/удалитель точно закоммитился / откатился». Стоит такой флаг - и clog трогать не надо.

Подводный камень: SELECT, который пишет

Вот неожиданность. Подсказку ставит первый, кто прочитал строку после того, как её транзакция завершилась. Установка подсказки меняет байты страницы, а значит, помечает её грязной - и страница будет записана на диск. Получается, что безобидный с виду SELECT сразу после массовой загрузки данных вызывает шквал записи: он расставляет подсказки по всем свежим строкам.

sql
SELECT t_infomask::bit(16)
FROM heap_page_items(get_raw_page('mv', 0));
-- первый SELECT после коммита расставит hint bits;
-- повторный покажет уже выставленные флаги

Поэтому «холодное» первое чтение только что загруженной таблицы бывает заметно дороже последующих - и удивляет тех, кто считает SELECT бесплатным по записи. Это не утечка и не баг, а отложенная работа по фиксации статуса.

§ команды

bash
SELECT t_infomask::bit(16) FROM heap_page_items(get_raw_page('mv', 0));

Флаги строки, включая подсказки фиксации xmin/xmax

bash
SELECT (t_infomask & 256) <> 0 AS xmin_committed FROM heap_page_items(get_raw_page('mv', 0));

Проверить бит HEAP_XMIN_COMMITTED напрямую

bash
SELECT pg_xact_status(pg_current_xact_id());

Статус транзакции по clog: in progress / committed / aborted

§ см. также

  • xmin-xmaxxmin, xmax и правила видимостиУ каждой версии строки два транзакционных штампа: xmin (кто вставил) и xmax (кто пометил устаревшей, 0 - если жива). Версия видна транзакции, если её xmin уже зафиксирован и попадает в снимок, а xmax либо пуст, либо ещё не зафиксирован, либо не виден снимку. По этим двум числам строится вся видимость.
  • tuple-headerЗаголовок кортежаПеред данными каждой строки лежит служебный заголовок в 23 байта, выровненный до 24. В нём t_xmin и t_xmax (кто вставил и кто удалил версию), t_ctid (ссылка на себя или на новую версию), t_infomask с флагами и t_hoff - смещение до пользовательских данных. Это поля, на которых стоит весь MVCC.
  • subtransactionsВложенные транзакции и savepointsSAVEPOINT открывает вложенную транзакцию (подтранзакцию) внутри основной. ROLLBACK TO SAVEPOINT откатывает её работу, не трогая остальную транзакцию. Каждая пишущая подтранзакция получает свой xid, а связь «подтранзакция - родитель» хранит pg_subtrans. Блоки EXCEPTION в PL/pgSQL - это тоже подтранзакции.
Footer
linuxlab-
Copyright © 2026 LinuxLab. Все права защищены.
Учебники
Цены
О платформе
Конфиденциальность и куки