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/Хранение и формат на диске/line-pointers

kb/storage ── Хранение и формат на диске ── intermediate

Line pointers и lp_flags

Указатель строки (line pointer) - это 4 байта в начале страницы: смещение до кортежа, его длина и флаг состояния. Флаг lp_flags бывает четырёх видов: unused, normal, redirect, dead. Внешний адрес строки (ctid) - это номер указателя, а не позиция в байтах, поэтому строка может двигаться внутри страницы, не меняя адреса.

view as markdownaka: line-pointer, item-pointer, lp-flags

Сразу за заголовком страницы идёт массив указателей строк (line pointers). Каждый указатель - всего 4 байта и описывает одну строку: где она лежит (смещение), сколько занимает (длина) и в каком она состоянии (флаг). Раскладку страницы целиком разбирает page-layout.

Указатель нужен, чтобы у строки был стабильный адрес. Адрес строки внутри таблицы - это пара «номер страницы, номер указателя», она же ctid. Когда страница уплотняется и кортеж физически переезжает, меняется только смещение внутри указателя. Номер указателя, а значит и ctid, остаётся прежним. Без этого слоя любое движение строки ломало бы ссылки на неё.

Четыре состояния указателя

Флаг lp_flags (2 бита) говорит, что за указателем стоит:

lp_flagsИмяСмысл
0LP_UNUSEDслот свободен, можно переиспользовать
1LP_NORMALведёт на нормальный кортеж
2LP_REDIRECTведёт на другой указатель (звено HOT-цепочки)
3LP_DEADстрока мертва, место под кортеж уже освобождено

Посмотреть флаги всех строк на странице:

sql
SELECT lp, lp_off, lp_len, lp_flags
FROM heap_page_items(get_raw_page('flights', 0));
--  lp | lp_off | lp_len | lp_flags
-- ----+--------+--------+----------
--   1 |   8144 |     48 |        1
--   2 |   8096 |     48 |        1

lp_flags = 1 (LP_NORMAL) - обычная живая строка. lp_off - смещение кортежа от начала страницы, lp_len - его длина в байтах. Указатели лежат по возрастанию (1, 2, 3 ...), а смещения lp_off убывают: кортежи заполняют страницу с конца.

Redirect и dead - следы очистки

Два «странных» состояния появляются после обновлений и очистки.

LP_REDIRECT возникает при внутристраничной очистке HOT-цепочки. Когда старая версия строки удаляется, но на её указатель ещё ссылаются, указатель превращают в перенаправление: он не хранит кортеж, а отправляет к началу живой цепочки версий. lp_len у такого указателя равен 0.

LP_DEAD помечает указатель, чья строка уже не видна ни одной транзакции. Место под сам кортеж может быть уже освобождено, а указатель ждёт, когда его переведут в UNUSED. Это промежуточное состояние между «живой» и «полностью свободный».

Зачем это знать

Когда в heap_page_items встречаются нули в lp_len или флаги 2 и 3 - это не мусор, а рабочая механика. Redirect-указатели объясняют, почему обновление строки иногда не трогает индекс. Dead-указатели показывают, что вакуум уже прошёлся по странице. Без этого слоя не понять ни HOT, ни то, как ctid остаётся валидным, пока строка ездит по странице.

§ команды

bash
SELECT lp, lp_off, lp_len, lp_flags FROM heap_page_items(get_raw_page('flights', 0));

Все указатели строк на странице 0: смещение, длина, флаг состояния

bash
SELECT ctid, * FROM flights LIMIT 3;

Системная колонка ctid - пара (страница, номер указателя)

bash
SELECT count(*) FILTER (WHERE lp_flags = 2) AS redirects FROM heap_page_items(get_raw_page('t', 0));

Сколько на странице redirect-указателей (следов HOT-очистки)

§ см. также

  • page-layoutРаскладка страницы 8 КБТаблица на диске - это массив страниц по 8 КБ. Внутри страницы четыре зоны: заголовок 24 байта, массив указателей строк (растёт сверху вниз), свободное место и сами кортежи (растут снизу вверх). У heap-страницы спецзона в конце пустая. Указатели и кортежи движутся навстречу.
  • tuple-headerЗаголовок кортежаПеред данными каждой строки лежит служебный заголовок в 23 байта, выровненный до 24. В нём t_xmin и t_xmax (кто вставил и кто удалил версию), t_ctid (ссылка на себя или на новую версию), t_infomask с флагами и t_hoff - смещение до пользовательских данных. Это поля, на которых стоит весь MVCC.
  • visibility-mapVisibility Map (карта видимости)Карта видимости (_vm) держит по два бита на страницу: all-visible (все строки видны всем) и all-frozen (все строки заморожены). Первый бит позволяет index-only scan не ходить в таблицу за проверкой видимости, а вакууму - пропускать страницу. Биты ставит VACUUM и сбрасывает любая запись в страницу.
Footer
linuxlab-
Copyright © 2026 LinuxLab. Все права защищены.
Учебники
Цены
О платформе
Конфиденциальность и куки