Ответ
Уровни изоляции транзакций определяют, насколько транзакции изолированы друг от друга, балансируя между целостностью данных и производительностью. Стандарт SQL определяет четыре уровня (от самого слабого к самому строгому).
Уровни изоляции и решаемые аномалии
| Уровень | Грязное чтение (Dirty Read) | Неповторяющееся чтение (Non-repeatable Read) | Фантомное чтение (Phantom Read) |
|---|---|---|---|
| READ UNCOMMITTED | ❌ Возможно | ❌ Возможно | ❌ Возможно |
| READ COMMITTED | ✅ Решено | ❌ Возможно | ❌ Возможно |
| REPEATABLE READ | ✅ Решено | ✅ Решено | ❌ Возможно |
| SERIALIZABLE | ✅ Решено | ✅ Решено | ✅ Решено |
Описание уровней
-
READ UNCOMMITTED
- Транзакция видит незафиксированные изменения других транзакций.
- Проблема: Грязное чтение — можно прочитать данные, которые потом будут откачены.
- Использование: Редко, в сценариях, где важна максимальная скорость, а целостность данных второстепенна.
-
READ COMMITTED
- Транзакция видит только зафиксированные данные других транзакций. Это уровень по умолчанию в PostgreSQL и Oracle.
- Проблема: Неповторяющееся чтение — повторное чтение одной строки в рамках транзакции может вернуть разные данные, если другая транзакция изменила и зафиксировала эту строку.
-
REPEATABLE READ
- Гарантирует, что строки, прочитанные один раз в транзакции, не изменятся другими транзакциями до её завершения. Это уровень по умолчанию в MySQL (InnoDB).
- Проблема: Фантомное чтение — появление новых строк, удовлетворяющих условию запроса, из-за вставок другими транзакциями.
-
SERIALIZABLE
- Самый строгий уровень. Гарантирует полную изоляцию, как если бы транзакции выполнялись последовательно.
- Достигается блокировками или управлением версиями данных (MVCC).
- Недостаток: Наибольшее влияние на производительность и параллелизм.
Пример настройки в JDBC
Connection connection = dataSource.getConnection();
// Установка уровня изоляции для текущего соединения
connection.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);
// Или при старте транзакции
connection.setAutoCommit(false); Ответ 18+ 🔞
Ну, вот смотри, как это в жизни работает, а то в книжках пишут про транзакции — мозг вытекает. Представь, что база данных — это общага, а транзакции — это соседи, которые пытаются одновременно в холодильник залезть. Уровни изоляции — это правила, кто кого видит и кто кому может бутерброд из рук выхватить.
Вот таблица, которая всё объясняет, но я её на пальцах разжую, а то там одни галочки.
Уровни изоляции и какие косяки они решают (или не решают)
| Уровень | Грязное чтение | Неповторяющееся чтение | Фантомное чтение |
|---|---|---|---|
| READ UNCOMMITTED | ❌ МОЖНО | ❌ МОЖНО | ❌ МОЖНО |
| READ COMMITTED | ✅ НЕЛЬЗЯ | ❌ МОЖНО | ❌ МОЖНО |
| REPEATABLE READ | ✅ НЕЛЬЗЯ | ✅ НЕЛЬЗЯ | ❌ МОЖНО |
| SERIALIZABLE | ✅ НЕЛЬЗЯ | ✅ НЕЛЬЗЯ | ✅ НЕЛЬЗЯ |
А теперь на человеческом, блядь
-
READ UNCOMMITTED (Читай что попало)
- Это как подслушивать у двери, пока сосед с девушкой ругается. Ты слышишь всё: и крики, и обещания, и угрозы разойтись. А потом они помирились, пошли чай пить, а у тебя в голове — драма на три акта, которой на хуй никому не надо. Ты прочитал грязные, незафиксированные данные, которые потом откатились. Используют эту хуйню только отчаяные перформанс-хуесосы, которым похуй на целостность, лишь бы быстро.
-
READ COMMITTED (Читай только подтверждённое)
- Уже лучше. Ты видишь только то, что сосед уже сделал и не собирается откатывать. Зашёл в холодильник — там три сосиски. Отошёл за хлебом, вернулся — а сосиски уже сожрал другой сосед и тарелку помыл. Ты прочитал одно значение, а через секунду в той же транзакции — уже другое. Это и есть «неповторяющееся чтение». В Постгресе и Оракуле это стоит по умолчанию, народ привыкший.
-
REPEATABLE READ (Повторяемое чтение)
- Вот тут уже магия начинается. Ты как будто делаешь снимок холодильника в момент начала своей операции. Ты запомнил, что там три сосиски. Пока твоя транзакция не закончится, для тебя их так и будет три, даже если весь этаж уже обожрался и стошнил. Проблема в другом — фантомы. Ты запомнил, что сосисок три. Но ты не запомнил, что вообще в холодильнике может что-то появиться. А пока ты считал сосиски, кто-то мог засунуть туда тарелку с селёдкой. И когда ты пойдёшь «посмотреть, что есть в холодильнике» второй раз — бац, а там селёдка! Откуда? Фантом, блядь! В MySQL (InnoDB) это дефолт, они там свои заморочки с gap locks имеют.
-
SERIALIZABLE (Последовательный)
- Абсолютная власть, ёпта! Это когда в холодильник имеет право заглядывать строго по одному человеку, и дверь закрывается. Все стоят в очереди. Никаких грязных чтений, никаких изменений на лету, никаких фантомных селёдок. Полный порядок и… овердохуища простоев. Производительность летит в пизду, зато данные целы. Используют, когда ошибка стоит дороже, чем время ожидания.
Как это в коде выглядит (блок не трогаю, он святой)
Connection connection = dataSource.getConnection();
// Говорим джаве: "Слушай, делай мне REPEATABLE READ, я не хочу, чтобы мои сосиски пропадали!"
connection.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);
// Или так, когда транзакцию начинаем
connection.setAutoCommit(false);
Короче, выбирай уровень, как кондом: самый тонкий — рискованно, но чувствительно; самый надёжный — безопасно, но как в скафандре. Серединка (REPEATABLE READ или READ COMMITTED) — обычно то, что надо.