lesson ── postgres-labs ── ~22 мин ── 5 шагов
xid - 32-битное число, и таблица «стареет» по мере того, как счётчик
транзакций уходит вперёд. Возраст показывает age(relfrozenxid). Если
он дорастёт до опасной черты - грозит wraparound. Сейчас ты искусственно
состаришь таблицу, увидишь рост возраста, а потом VACUUM FREEZE вернёт
его почти к нулю. Перед каждым шагом предскажи, как изменится age().
интерактивный sandbox
Поднимется контейнер postgreslab/postgres-base с PostgreSQL 17 и psql. В браузере откроется терминал, база lab уже настроена. Каждый шаг проверяется автоматически. Сеть air-gapped, наружу контейнер не ходит.
stack ── PostgreSQL 17 · psql · 1 GB RAM · air-gapped · самоуничтожается через 45 мин простоя
SELECT relname, age(relfrozenxid) AS xid_age
FROM pg_class WHERE relname = 'flights';
Это на сколько транзакций граница заморозки flights отстала от
текущего счётчика. Запомни число.
✓ Базовый возраст снят.
Каждая закоммиченная транзакция двигает счётчик вперёд и увеличивает возраст всех незамороженных таблиц. Сожжём около тысячи коротких транзакций из шелла:
for i in $(seq 1 1100); do psql -tAc "SELECT txid_current()" >/dev/null; done
Затем снова сними возраст flights. Предскажи: вырастет ли он
примерно на тысячу?
Каждый отдельный psql -c — это своя транзакция, то есть свой xid.
✓ Возраст вырос — таблица «постарела» на сожжённые транзакции.
VACUUM FREEZE flights;
SELECT age(relfrozenxid) FROM pg_class WHERE relname = 'flights';
VACUUM FREEZE морозит все пригодные версии и продвигает
relfrozenxid почти к текущему счётчику. Предскажи: каким станет
возраст?
✓ Возраст упал — заморозка отодвинула таблицу от опасной черты.
У wraparound есть младший брат - multixact, со своей границей
relminmxid и своим возрастом. Мониторинг про него часто забывает.
SELECT relname,
age(relfrozenxid) AS xid_age,
mxid_age(relminmxid) AS mxid_age
FROM pg_class WHERE relname = 'flights';
Следить нужно за обоими возрастами, не только за xid_age.
✓ Возраст multixact на месте — теперь ты следишь за обоими счётчиками.
Так в проде ищут таблицу, которую autovacuum не успевает морозить:
SELECT relname, age(relfrozenxid) AS xid_age
FROM pg_class WHERE relkind = 'r'
ORDER BY age(relfrozenxid) DESC
LIMIT 5;
Если у какой-то таблицы возраст упорно ползёт к 200 млн - пора разбираться, почему её не чистят.
✓ Ты умеешь находить самые старые таблицы — главный приём защиты от wraparound.
Таблица стареет с ростом счётчика транзакций; age(relfrozenxid) показывает дистанцию до wraparound. VACUUM FREEZE морозит версии и продвигает relfrozenxid, сбрасывая возраст. За multixact следят отдельно через mxid_age(relminmxid).
команды
SELECT age(relfrozenxid) FROM pg_class WHERE relname='flights';возраст таблицы в транзакцияхVACUUM FREEZE flights;заморозить и продвинуть relfrozenxidSELECT relname, age(relfrozenxid) FROM pg_class ORDER BY 2 DESC;самые старые таблицыконцепции