TGViewer
Fedkin is thinking Fedkin is thinking @fedkin_thinking · 9.01K subscribers
Post #140 11.6K
Принцип работы snapshot isolation (aka repeatable read) в postgres

Изоляция repeatable read избавляет от неповторяющегося чтения — ситуации, когда одна и та же строка запрашивается дважды в рамках транзакции, но результаты чтения получаются разными

begin;

select * from t where id = 1 <- отдает одно значение

-- другая транзакция обновляет запись

select * from t where id = 1 <- отдает уже другое значение
...


Как это работает в postgres:

- Каждой транзакции присваивается xid — монотонно возрастающий идентификатор транзакции
- MVCC: одновременно поддерживаются несколько версий строк
- У каждой версии строки есть два системных поля: xmin, xmax

xmin — идентификатор транзакции, который создал версию строки
xmax — идентификатор транзакции, который удалил версию строки (т.е. сделал update либо delete)

---

Отсюда возникает довольно логичная концепция — при начале repeatable read транзакции "берем снапшот":

1. Назначаем текущей транзакции некоторый xid
2. В транзакции работаем только с версиями строк, где
- либо xmin < xid < xmax — версия строки создана до текущей транзакции, а удалена уже после начала текущей
- либо xmin < xid && xmax = 0 — версия строки создана до текущей транзакции, но еще никем не удалена

---

Однако возникает следующая проблема — на момент взятия снапшота может быть активная транзакция с xid меньшим, чем у снапшота. Когда она закоммитится, то для новосозданных строк будет выполняться условие xmin < xid && xmax = 0, и мы в текущей repeatable read транзакции увидим эту версию строки. Хотя при взятии снапшота этой версии еще не было — снова можем получить неповторяющееся чтение

Это решается следующим образом:

При взятии снапшота берется не только xid, но и также снапшотится список текущих транзакций. Это позволяет в снапшоте игнорировать записи, которые были закомиченны транзакциями, которые еще были активны на момент взятия снапшота

Таким образом, условие "видимости записей" будет таким

1. Берем снапшот: xid + active_xids
2. В транзакции работаем только с версиями строк, где

(xmin < xid < xmax || xmin < xid && xmax = 0)
&&
(xmin not in active_xids)


Хорошая статья по теме https://mbukowicz.github.io/databases/2020/05/01/snapshot-isolation-in-postgresql.html
  • 👍 66
  • 🔥 23
More from @fedkin_thinking
  1. Sep 20, 2026С большинством людей все в порядке Представь, у тебя команда регулярно срывает сроки ревью…
  2. Sep 19, 2026Чему техлиду научиться у Tinder На днях стало интересно, как запускаются сервисы с "сетевы…
  3. Sep 13, 2026Почему рабочие встречи превращаются в балаган — Раскатываем эксп на 100%? — Я бы не раскат…
  4. Sep 12, 2026Перед автоматизацией выясни, существует ли процесс Нулевой шаг автоматизации абсолютно чег…
  5. Aug 31, 2026Полезно понимать, какие проблемы решает твой руководитель Повышение обычно происходит, ког…
  6. Aug 29, 2026Все заняты, а продукт не двигается — Миш, вижу у тебя десять задач по бэку, какой статус?…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →