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 -> снова 100MVCC
Строка имеет несколько версий, а транзакция читает версию, видимую ее снимку. Это уменьшает конкуренцию обычных чтений и записей, но не превращает систему в полную копию базы на диске для каждой транзакции.
Цена:
- хранение и очистка старых версий;
- рост таблиц/журнала при долгих транзакциях;
- необходимость разрешать 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? Не обязательно; зависит от реализации.
Почему вредны долгие транзакции? Они удерживают старый снимок и мешают очистке версий.