Repeatable Read

На уровне REPEATABLE READ повторное чтение одной строки в транзакции не должно показать новое зафиксированное значение другой транзакции. Часто это реализовано через MVCC-снимок.

T1: BEGIN
T1: SELECT total FROM orders WHERE id = 42  -> 100
T2: UPDATE orders SET total = 200 WHERE id = 42; COMMIT
T1: SELECT total FROM orders WHERE id = 42  -> снова 100

MVCC

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

Цена:

  • хранение и очистка старых версий;
  • рост таблиц/журнала при долгих транзакциях;
  • необходимость разрешать write-write conflicts;
  • возможные аномалии на уровне нескольких строк.

Repeatable Read не всегда равно Snapshot Isolation

Это связанные, но не тождественные термины:

  • REPEATABLE READ — имя уровня SQL и набор минимальных гарантий;
  • snapshot isolation — конкретная модель чтения из снимка и проверки конфликтов.

Разные СУБД под одним именем дают разные свойства. В частности, snapshot isolation может допустить write skew:

Правило: хотя бы один дежурный остается.
T1 и T2 видят двух дежурных.
T1 снимает с дежурства A, T2 — B.
Обе меняют разные строки и фиксируются: правило нарушено.

Когда нужно актуальное состояние

Для решения «прочитать, затем изменить» используют атомарный UPDATE, optimistic version или SELECT ... FOR UPDATE. Обычный snapshot-read не резервирует строку.

Связано: Изоляция транзакций, Lost Update, Опасности использования read committed.

Вопросы

Создает ли СУБД полную копию базы? Нет, видимость строится по версиям и метаданным снимка.

Блокирует ли обычное чтение запись при MVCC? Обычно нет.

Предотвращает ли Repeatable Read write skew? Не обязательно; зависит от реализации.

Почему вредны долгие транзакции? Они удерживают старый снимок и мешают очистке версий.