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= Committed10= Aborted11= 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) | Не узнаем статус → не поймём, видна строка или нет |