Какие существуют уровни изоляции транзакций в SQL и чем они отличаются?

Ответ

Уровни изоляции транзакций определяют, насколько транзакции изолированы друг от друга, балансируя между целостностью данных и производительностью. Стандарт SQL определяет четыре уровня (от самого слабого к самому строгому).

Уровни изоляции и решаемые аномалии

Уровень Грязное чтение (Dirty Read) Неповторяющееся чтение (Non-repeatable Read) Фантомное чтение (Phantom Read)
READ UNCOMMITTED ❌ Возможно ❌ Возможно ❌ Возможно
READ COMMITTED ✅ Решено ❌ Возможно ❌ Возможно
REPEATABLE READ ✅ Решено ✅ Решено ❌ Возможно
SERIALIZABLE ✅ Решено ✅ Решено ✅ Решено

Описание уровней

  1. READ UNCOMMITTED

    • Транзакция видит незафиксированные изменения других транзакций.
    • Проблема: Грязное чтение — можно прочитать данные, которые потом будут откачены.
    • Использование: Редко, в сценариях, где важна максимальная скорость, а целостность данных второстепенна.
  2. READ COMMITTED

    • Транзакция видит только зафиксированные данные других транзакций. Это уровень по умолчанию в PostgreSQL и Oracle.
    • Проблема: Неповторяющееся чтение — повторное чтение одной строки в рамках транзакции может вернуть разные данные, если другая транзакция изменила и зафиксировала эту строку.
  3. REPEATABLE READ

    • Гарантирует, что строки, прочитанные один раз в транзакции, не изменятся другими транзакциями до её завершения. Это уровень по умолчанию в MySQL (InnoDB).
    • Проблема: Фантомное чтение — появление новых строк, удовлетворяющих условию запроса, из-за вставок другими транзакциями.
  4. SERIALIZABLE

    • Самый строгий уровень. Гарантирует полную изоляцию, как если бы транзакции выполнялись последовательно.
    • Достигается блокировками или управлением версиями данных (MVCC).
    • Недостаток: Наибольшее влияние на производительность и параллелизм.

Пример настройки в JDBC

Connection connection = dataSource.getConnection();
// Установка уровня изоляции для текущего соединения
connection.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);
// Или при старте транзакции
connection.setAutoCommit(false);

Ответ 18+ 🔞

Ну, вот смотри, как это в жизни работает, а то в книжках пишут про транзакции — мозг вытекает. Представь, что база данных — это общага, а транзакции — это соседи, которые пытаются одновременно в холодильник залезть. Уровни изоляции — это правила, кто кого видит и кто кому может бутерброд из рук выхватить.

Вот таблица, которая всё объясняет, но я её на пальцах разжую, а то там одни галочки.

Уровни изоляции и какие косяки они решают (или не решают)

Уровень Грязное чтение Неповторяющееся чтение Фантомное чтение
READ UNCOMMITTED ❌ МОЖНО ❌ МОЖНО ❌ МОЖНО
READ COMMITTED ✅ НЕЛЬЗЯ ❌ МОЖНО ❌ МОЖНО
REPEATABLE READ ✅ НЕЛЬЗЯ ✅ НЕЛЬЗЯ ❌ МОЖНО
SERIALIZABLE ✅ НЕЛЬЗЯ ✅ НЕЛЬЗЯ ✅ НЕЛЬЗЯ

А теперь на человеческом, блядь

  1. READ UNCOMMITTED (Читай что попало)

    • Это как подслушивать у двери, пока сосед с девушкой ругается. Ты слышишь всё: и крики, и обещания, и угрозы разойтись. А потом они помирились, пошли чай пить, а у тебя в голове — драма на три акта, которой на хуй никому не надо. Ты прочитал грязные, незафиксированные данные, которые потом откатились. Используют эту хуйню только отчаяные перформанс-хуесосы, которым похуй на целостность, лишь бы быстро.
  2. READ COMMITTED (Читай только подтверждённое)

    • Уже лучше. Ты видишь только то, что сосед уже сделал и не собирается откатывать. Зашёл в холодильник — там три сосиски. Отошёл за хлебом, вернулся — а сосиски уже сожрал другой сосед и тарелку помыл. Ты прочитал одно значение, а через секунду в той же транзакции — уже другое. Это и есть «неповторяющееся чтение». В Постгресе и Оракуле это стоит по умолчанию, народ привыкший.
  3. REPEATABLE READ (Повторяемое чтение)

    • Вот тут уже магия начинается. Ты как будто делаешь снимок холодильника в момент начала своей операции. Ты запомнил, что там три сосиски. Пока твоя транзакция не закончится, для тебя их так и будет три, даже если весь этаж уже обожрался и стошнил. Проблема в другом — фантомы. Ты запомнил, что сосисок три. Но ты не запомнил, что вообще в холодильнике может что-то появиться. А пока ты считал сосиски, кто-то мог засунуть туда тарелку с селёдкой. И когда ты пойдёшь «посмотреть, что есть в холодильнике» второй раз — бац, а там селёдка! Откуда? Фантом, блядь! В MySQL (InnoDB) это дефолт, они там свои заморочки с gap locks имеют.
  4. SERIALIZABLE (Последовательный)

    • Абсолютная власть, ёпта! Это когда в холодильник имеет право заглядывать строго по одному человеку, и дверь закрывается. Все стоят в очереди. Никаких грязных чтений, никаких изменений на лету, никаких фантомных селёдок. Полный порядок и… овердохуища простоев. Производительность летит в пизду, зато данные целы. Используют, когда ошибка стоит дороже, чем время ожидания.

Как это в коде выглядит (блок не трогаю, он святой)

Connection connection = dataSource.getConnection();
// Говорим джаве: "Слушай, делай мне REPEATABLE READ, я не хочу, чтобы мои сосиски пропадали!"
connection.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);
// Или так, когда транзакцию начинаем
connection.setAutoCommit(false);

Короче, выбирай уровень, как кондом: самый тонкий — рискованно, но чувствительно; самый надёжный — безопасно, но как в скафандре. Серединка (REPEATABLE READ или READ COMMITTED) — обычно то, что надо.