Ответ
Уровни изоляции транзакций определяют, насколько изменения в одной транзакции видны другим параллельным транзакциям, и какие аномалии чтения они предотвращают. В MySQL InnoDB поддерживаются четыре стандартных уровня:
- READ UNCOMMITTED: Самый низкий уровень. Возможно «грязное чтение» — транзакция видит незафиксированные изменения другой транзакции.
- READ COMMITTED: Транзакция видит только зафиксированные данные. Предотвращает грязное чтение, но возможны «неповторяющееся чтение» (одна и та же строка, прочитанная дважды, может измениться) и «фантомное чтение» (появление новых строк).
- REPEATABLE READ (уровень по умолчанию для InnoDB): Гарантирует, что данные, прочитанные в течение транзакции, не изменятся. Предотвращает грязное и неповторяющееся чтение. InnoDB также предотвращает фантомное чтение за счёт механизма gap-блокировок.
- SERIALIZABLE: Самый строгий уровень. Транзакции изолируются полностью, как если бы выполнялись последовательно. Достигается за счёт блокировок на чтение.
Пример установки уровня:
-- Устанавливаем уровень изоляции для текущей сессии
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
START TRANSACTION;
SELECT * FROM orders WHERE user_id = 100; -- Этот «снимок» данных будет неизменным до конца транзакции
-- ... некоторая логика ...
COMMIT;
На практике чаще всего работаю с уровнем по умолчанию REPEATABLE READ, так как он обеспечивает хороший баланс между согласованностью и производительностью для большинства задач.
Ответ 18+ 🔞
Слушай, давай разберём эту тему про уровни изоляции, а то звучит страшно, а на деле — просто про то, кто кого и когда видит в базе. Представь, что у тебя в офисе несколько человек лезут в один холодильник с пивом одновременно. Вот чтобы не было пиздеца, и нужны эти правила.
В общем, есть четыре уровня, от полного бардака до армейской дисциплины.
-
READ UNCOMMITTED (Чтение незафиксированного). Это как будто ты заглядываешь в рот соседу, пока он жуёт. Видишь, что у него там котлета, но он ещё может её выплюнуть, если подавится. В терминах баз — твоя транзакция видит грязные, незафиксированные данные от других. Может увидеть цифру, которой через секунду не станет. Пиздец, а не уровень. Использовать — это вы ходите по охуенно тонкому льду. Доверия к данным — ноль ебать.
-
READ COMMITTED (Чтение зафиксированного). Уже адекватнее. Ты видишь в холодильнике только то пиво, которое кто-то уже точно поставил и закрыл дверцу. То есть только закоммиченные данные. Грязное чтение отваливается. Но есть подлянка: неповторяющееся чтение. Ты посмотрел — там одно пиво. Отвернулся за стаканом, а какой-то пидарас шерстяной уже твоё пиво взял. Второй раз глянул — а его нет! Или наоборот, появилось новое (фантомное чтение). В общем, данные между двумя твоими одинаковыми запросами могут измениться. Подозрение ебать чувствую к такому.
-
REPEATABLE READ (Повторяемое чтение). Уровень по умолчанию в InnoDB, и неспроста! Это как сделать моментальный снимок (снепшот) холодильника в начале твоей пьянки. Ты открываешь транзакцию — и всё, фотофиксация. Сколько бы раз ты потом ни смотрел, в рамках этой транзакции ты будешь видеть одну и ту же картину: те же три банки, даже если в реальности они уже кончились. InnoDB ещё и фантомы ловит своими
gap locks(защёлками на промежутки), так что новые банки на полке тоже не материализуются. Баланс идеальный — и согласованность есть, и не душим всё нахер блокировками. Для 95% случаев — то, что надо. -
SERIALIZABLE (Упорядочиваемый). Полный параноидальный режим. Это когда на холодильник вешают замок и выстраивают очередь. Один взял — закрыл, следующий открыл. Транзакции выполняются так, будто они идут строго одна за другой. Согласованность — овердохуища, но производительность может накрыться медным тазом, потому что даже для простого
SELECTставятся блокировки.
Вот как это примерно в коде выглядит:
-- Говорим MySQL: на время этой сессии, давай по уровню REPEATABLE READ
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
START TRANSACTION;
-- С этого момента для меня мир застыл. Что бы там ни творилось,
-- этот запрос всегда вернет одни и те же данные для user_id = 100
SELECT * FROM orders WHERE user_id = 100;
-- ... какая-то своя бизнес-логика ...
COMMIT; -- Теперь отпускаю снимок, мир снова может меняться
Короче, если не знаешь, что выбрать — да похуй, оставляй REPEATABLE READ по умолчанию, InnoDB умная, сама разберётся. Лезешь в какие-то сверхточные финансовые отчёты с кучей параллельных правок — тогда уже думай про SERIALIZABLE. А READ UNCOMMITTED — это для отчаянных, у которых терпения ноль ебать ждать.