Что такое MVCC и как он реализован в PostgreSQL?
MVCC (Multi-Version Concurrency Control) — механизм управления конкурентным доступом, при котором каждая транзакция видит свой «снимок» (snapshot) данных. Главный принцип: читатели не блокируют писателей, а писатели не блокируют читателей.
Аналогия из жизни: MVCC — это как Google Docs с историей версий. Каждый пользователь видит свою версию документа на момент открытия, а изменения других пользователей появляются только после «обновления страницы» (нового оператора или транзакции).
Реализация в PostgreSQL
Каждая строка (tuple) содержит скрытые системные столбцы:
xmin— ID транзакции, которая создала эту версию строкиxmax— ID транзакции, которая удалила (или обновила) эту версию (0, если строка «живая»)ctid— физический адрес строки на странице
Что происходит при UPDATE
- Текущая версия строки не изменяется — у неё устанавливается
xmaxравным ID текущей транзакции - Создаётся новая версия строки с изменёнными данными,
xmin= ID текущей транзакции - Обе версии физически присутствуют в таблице
Пример
-- Наглядно: смотрим системные столбцы
SELECT xmin, xmax, ctid, * FROM accounts WHERE id = 1;
-- Результат: xmin=100, xmax=0, ctid=(0,1), id=1, balance=5000
-- После UPDATE в другой транзакции (txid=200):
-- Старая версия: xmin=100, xmax=200, ctid=(0,1)
-- Новая версия: xmin=200, xmax=0, ctid=(0,5)
Видимость строк
Транзакция видит строку, если:
xminзафиксирована (committed) и < ID текущей транзакции (или это она сама)xmaxне установлен (0) или не зафиксирован, или > ID текущей транзакции
Последствия MVCC
- При обновлении и удалении создаются «мёртвые» (dead) версии, которые занимают место
- Необходим процесс VACUUM для очистки мёртвых версий
- Индексы также содержат ссылки на все версии строк
- Таблицы могут «раздуваться» (table bloat) без регулярного VACUUM
Преимущества MVCC
- Читатели не блокируют писателей — высокая производительность при конкурентном доступе
- Консистентные snapshot-чтения без блокировок
- Это фундамент всех уровней изоляции в PostgreSQL
На собеседовании: MVCC — один из самых частых вопросов по PostgreSQL. Обязательно упомяните xmin/xmax и то, что UPDATE создаёт новую версию строки (а не изменяет существующую). Связка MVCC -> dead tuples -> VACUUM показывает системное понимание.