Какие уровни изоляции транзакций существуют и какие аномалии они допускают?
Короткий ответ
- Read Uncommitted допускает грязное чтение
- Read Committed убирает грязное чтение, но есть неповторяющееся чтение
- Repeatable Read фиксирует снимок, остаются фантомы и аномалии записи
- Serializable — как будто транзакции шли по очереди
- В PostgreSQL дефолт — Read Committed, работает через MVCC
- Чем строже уровень, тем больше конфликтов и ретраев
Уровни изоляции — компромисс между корректностью и конкурентностью: от грязного чтения до полной сериализуемости.
Как сказать вслух
пример ответаСтандарт описывает четыре уровня. Read Uncommitted позволяет читать незакоммиченные данные. Read Committed, дефолт в Postgres, показывает только закоммиченное, но два одинаковых запроса в одной транзакции могут вернуть разное. Repeatable Read работает со снимком на начало транзакции. Serializable гарантирует результат, как будто транзакции выполнялись по очереди. На практике чем строже уровень, тем чаще конфликты, и код должен уметь повторять транзакцию.
Подробный ответ
Основной ответ
Уровни изоляции определяют, какие аномалии конкурентного доступа допустимы. Dirty read — чтение незакоммиченных данных (допускается только на Read Uncommitted; в PostgreSQL его фактически нет). Non-repeatable read — повторное чтение той же строки даёт другой результат, потому что параллельная транзакция закоммитила изменение (возможно на Read Committed). Phantom read — повторный запрос по условию возвращает новые строки. Repeatable Read в PostgreSQL реализован через MVCC-снимок и фантомов тоже не показывает, но допускает write skew — две транзакции читают пересекающиеся данные и пишут на основе устаревшего чтения. Serializable (в Postgres — SSI) отслеживает зависимости и прерывает одну из конфликтующих транзакций ошибкой сериализации, поэтому приложение обязано ретраить.
Ключевые моменты
- MVCC. PostgreSQL держит несколько версий строк: читатели не блокируют писателей и наоборот. Изоляция определяется тем, какой снимок видит транзакция.
- Write skew. Классика: два врача одновременно снимают с себя дежурство, каждый видит, что второй остаётся. Repeatable Read это пропустит, Serializable — поймает.
- Ретраи обязательны. На Repeatable Read и Serializable транзакция может завершиться ошибкой сериализации — код должен повторять её в цикле.
- Отличия СУБД. Repeatable Read в MySQL/InnoDB и PostgreSQL ведёт себя по-разному; стандарт описывает минимум, реализации различаются.
Практический контекст
На практике большинство приложений живёт на Read Committed, а точечную корректность добирают SELECT ... FOR UPDATE, уникальными ограничениями и атомарными UPDATE. Serializable включают для критичных денежных операций. Интервьюер любит дать сценарий (двойное списание, бронирование последнего места) и спросить, какой уровень или приём это закрывает — здесь проверяется не зубрёжка таблицы аномалий, а умение применять её.
Частые ошибки
- Пересказывают таблицу уровней, но не могут разобрать конкретный сценарий гонки
- Не знают про write skew и считают Repeatable Read полной защитой
- Забывают, что Serializable требует обработки ошибок сериализации и ретраев