# Уровни изоляции транзакций

> Уровни изоляции определяют, какие эффекты параллельных транзакций видны друг другу — от Read Uncommitted до Serializable — и какие аномалии при этом допускаются.

Источник: https://llmdocs.ru/wiki/isolation-levels/ · обновлено 2026-11-09 · лицензия CC BY-SA 4.0

- **Стандарт**: SQL-92 — четыре уровня
- **Уровни**: Read Uncommitted, Read Committed, Repeatable Read, Serializable
- **Аномалии стандарта**: грязное чтение, неповторяющееся чтение, фантомы
- **Дополнительные аномалии**: потерянное обновление, перекос записи (write skew)
- **Критика стандарта**: Беренсон и др. (1995)
- **По умолчанию**: Read Committed (PostgreSQL, Oracle, SQL Server), Repeatable Read (MySQL InnoDB)
**Уровень изоляции транзакций** — настройка СУБД, определяющая, насколько параллельно выполняющиеся [транзакции](https://llmdocs.ru/wiki/transaction-acid.md) изолированы друг от друга: видит ли одна транзакция незафиксированные или только что зафиксированные изменения другой. Полная изоляция — результат как при последовательном выполнении — дорога, поэтому стандарт [SQL](https://llmdocs.ru/wiki/sql.md) определяет несколько уровней, на которых ради производительности допускаются те или иные **аномалии**.

Уровень изоляции — буква «I» в ACID и частый источник тонких ошибок: код, правильно работающий в тестах с одним пользователем, под нагрузкой теряет обновления или нарушает бизнес-правила.

## Аномалии

| Аномалия | Что происходит |
|---|---|
| Грязное чтение (*dirty read*) | транзакция видит изменения другой, ещё не зафиксированные (и, возможно, отменённые) |
| Неповторяющееся чтение (*non-repeatable read*) | повторное чтение той же строки даёт другое значение — её изменили и зафиксировали |
| Фантомы (*phantom read*) | повторный запрос с тем же условием возвращает новые строки |
| Потерянное обновление (*lost update*) | две транзакции читают значение, меняют его и записывают — одно изменение теряется |
| Перекос записи (*write skew*) | две транзакции читают общие данные, принимают решения и меняют *разные* строки, вместе нарушая правило |

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

## Уровни стандарта

| Уровень | Грязное чтение | Неповторяющееся чтение | Фантомы |
|---|---|---|---|
| Read Uncommitted | возможно | возможно | возможны |
| Read Committed | нет | возможно | возможны |
| Repeatable Read | нет | нет | возможны |
| Serializable | нет | нет | нет |

Уже в 1995 году Беренсон и соавторы показали, что определения стандарта неполны и неоднозначны: они не учитывают потерянные обновления и перекос записи и не описывают широко используемую **изоляцию снимков** (*snapshot isolation*), при которой транзакция видит согласованный снимок базы на момент начала.[1] Поэтому реальные СУБД под одинаковыми названиями дают разные гарантии.

## Как это реализовано

### PostgreSQL

Благодаря [MVCC](https://llmdocs.ru/wiki/mvcc.md) читатели никогда не блокируют писателей.[2]

- **Read Committed** (по умолчанию) — каждый оператор видит данные, зафиксированные к моменту его начала. Грязного чтения нет, но два `SELECT` в одной транзакции могут увидеть разное.
- **Repeatable Read** — изоляция снимков: вся транзакция видит один снимок. При попытке изменить строку, которую уже изменила параллельная транзакция, возникает ошибка сериализации. Фантомов нет, но перекос записи возможен.
- **Serializable** — сериализуемая изоляция снимков (SSI, с версии 9.1): поверх снимков СУБД отслеживает опасные зависимости чтения и записи и прерывает одну из транзакций, если результат не мог бы получиться при последовательном выполнении.[3]
- Read Uncommitted ведёт себя как Read Committed.

### Другие СУБД

- **MySQL InnoDB** по умолчанию использует Repeatable Read: обычные чтения идут по снимку, а блокирующие чтения и изменения — с блокировками промежутков индекса (*gap locks*), предотвращающими фантомы.[4]
- **Oracle** по умолчанию — Read Committed; его уровень Serializable на деле является изоляцией снимков.
- **[SQLite](https://llmdocs.ru/wiki/sqlite.md)** выполняет записывающие транзакции по одной, поэтому фактически сериализуема.

Сравнение гарантий разных систем и формальные модели согласованности собраны проектом Jepsen.[5]

## Как выбирать и что делать

```sql
BEGIN ISOLATION LEVEL SERIALIZABLE;
SELECT count(*) FROM doctors WHERE on_call AND shift_id = 42;
UPDATE doctors SET on_call = false WHERE id = 7 AND shift_id = 42;
COMMIT;   -- может завершиться ошибкой 40001: could not serialize access
```

1. **Read Committed** подходит для большинства запросов, если изменения выражены атомарно: `UPDATE accounts SET balance = balance - 100 WHERE id = 1 AND balance >= 100` вместо «прочитать в приложении — посчитать — записать».
2. **Явные блокировки** для критичных мест: `SELECT ... FOR UPDATE` блокирует прочитанные строки до конца транзакции и предотвращает потерянное обновление.
3. **Ограничения целостности** — `UNIQUE`, `CHECK`, исключающие ограничения — защищают инварианты на любом уровне изоляции.
4. **Serializable** — когда правила затрагивают несколько строк и их трудно выразить ограничениями. Приложение обязано уметь **повторять транзакцию** при ошибке сериализации (код 40001) — это нормальная часть работы, а не авария.
5. Держите транзакции короткими: чем дольше транзакция, тем выше вероятность конфликтов.

Подробный разбор аномалий с примерами — в книге Мартина Клеппмана «Высоконагруженные приложения».[6]

## См. также

- [Транзакция и ACID](https://llmdocs.ru/wiki/transaction-acid.md)
- [MVCC](https://llmdocs.ru/wiki/mvcc.md)
- [PostgreSQL](https://llmdocs.ru/wiki/postgresql.md)
- [Состояние гонки и блокировки](https://llmdocs.ru/wiki/race-conditions-locks.md)
- [Репликация баз данных](https://llmdocs.ru/wiki/replication.md)

## Источники

1. [H. Berenson et al. — A Critique of ANSI SQL Isolation Levels (SIGMOD 1995)](https://dl.acm.org/doi/10.1145/223784.223785)
2. [PostgreSQL Documentation — Transaction Isolation](https://www.postgresql.org/docs/current/transaction-iso.html)
3. [D. Ports, K. Grittner — Serializable Snapshot Isolation in PostgreSQL (VLDB 2012)](https://arxiv.org/abs/1208.4179)
4. [MySQL — Transaction Isolation Levels (InnoDB)](https://dev.mysql.com/doc/refman/8.4/en/innodb-transaction-isolation-levels.html)
5. [Jepsen — Consistency Models](https://jepsen.io/consistency)
6. [M. Kleppmann — Designing Data-Intensive Applications](https://dataintensive.net/)
