ProcArray

^psql-ProcArray ProcArray - содержит кто жив прямо сейчас:

  • Список активных (незавершённых) XID всех запущенных транзакций.
  • Также содержит xmin кластера — самый старый XID, который ещё может быть нужен (для определения, можно ли удалять старые строки).

ProcArray позволяет мгновенно определить статус “текущих” транзакций — без обращения к диску.

Где хранится?

  • shared memory
  • Процесс postmaster
  • Обновляется в реальном времени: при старте/завершении транзакции.

Пример:

  • ProcArray = [1001, 1003, 1007] → эти транзакции ещё работают.
  • Если t_xmin = 1003, и 1003 есть в ProcArray
    → строка ещё не видна (транзакция вставки не завершена).
  • Если t_xmax = 1001, и 1001 в ProcArray
    → строка ещё не удалена (транзакция удаления не завершена).

CLOG

^psql-clog архив статусов всех транзакций

Где хранится?

  • На диске, в каталоге PGDATA/pg_xact/.

  • Это битовая карта (bitmap), разбитая на сегменты по 256 КБ.

  • Каждый XID → 2 бита → статус:

    • 00 = In Progress (редко встречается на диске)
    • 01 = Committed
    • 10 = Aborted
    • 11 = Sub-transaction (специальный случай)
  • Также есть буфер CLOG в shared memory (обычно 8 страниц по 8 КБ) → кэширует недавние данные.

Зачем нужен?

  • Если транзакции нет в ProcArray, значит, она уже завершена.
  • Но как именно завершена? Успешно (COMMIT) или отменена (ABORT)?
  • ProcArray этого не знает. Для этого и нужен CLOG.

Пример:

  • Строка: t_xmin = 950
  • 950 нет в ProcArray → транзакция завершена.
  • Читаем CLOG → статус = Committed → строка видима.
  • Если статус = Aborted → строка никогда не существовала → пропускаем.

Чтение CLOG — потенциально медленная операция, поэтому есть кэш в shared memory (subtrans и clog buffers).

Важный нюанс: CLOG не обновляется при COMMIT

  • Когда транзакция делает COMMIT, её XID немедленно удаляется из ProcArray.
  • Но запись в CLOG может быть отложена!
  • Однако: WAL-запись COMMIT делается ДО возврата клиенту.
  • При восстановлении после сбоя: WAL проигрывается, и CLOG обновляется корректно.

Это безопасно благодаря WAL-first principle.


Почему нельзя обойтись только одним из них?

СценарийБез ProcArrayБез CLOG
Транзакция ещё работаетНе узнаем → можем подумать, что она уже завершена → увидим “грязные” данныеНе проблема (CLOG не содержит активных XID)
Транзакция завершилась 5 минут назадНе проблема (её нет в ProcArray)Не узнаем статус → не поймём, видна строка или нет