Ответ
В PostgreSQL параллельный доступ к данным реализован через механизм MVCC (Multi-Version Concurrency Control) — управление конкурентным доступом через многоверсионность. Это позволяет нескольким транзакциям читать и изменять данные одновременно, минимизируя блокировки.
Ключевые принципы:
- Снимки данных: Каждая транзакция работает со своим «снимком» (snapshot) данных, который был актуален на момент её начала. Она не видит изменений, сделанных другими транзакциями, которые начались позже.
- Версии строк: Вместо того чтобы изменять данные «на месте», PostgreSQL создает новую версию строки при каждом
UPDATE
. Старая версия не удаляется сразу, а помечается как неактуальная.
Как это работает на уровне строк:
Каждая строка в таблице имеет скрытые системные поля:
xmin
: ID транзакции, которая создала эту версию строки.xmax
: ID транзакции, которая удалила (или обновила) эту версию строки. Изначально равен 0.
Пример жизненного цикла строки:
-- 1. Транзакция с ID=100 вставляет новую строку.
-- Для этой строки xmin=100, xmax=0.
BEGIN; -- txid 100
INSERT INTO users (name) VALUES ('Alice');
COMMIT;
-- 2. Транзакция с ID=200 обновляет эту строку.
-- PostgreSQL выполняет два действия:
-- a) Помечает старую версию строки: xmax=200.
-- b) Создает новую версию строки с данными 'Bob' и xmin=200.
BEGIN; -- txid 200
UPDATE users SET name = 'Bob' WHERE name = 'Alice';
COMMIT;
Очистка старых версий:
«Мертвые» версии строк, которые больше не видны ни одной активной транзакции, удаляются фоновым процессом VACUUM
. Это необходимо для освобождения места и предотвращения разрастания таблиц.