Для чего нужно снижение уровня изоляции транзакций?

Ответ

Снижение уровня изоляции — это осознанный компромисс, на который я иду для увеличения пропускной способности (throughput) и уменьшения блокировок в высоконагруженных системах. Более строгие уровни (REPEATABLE READ, SERIALIZABLE) обеспечивают предсказуемость, но требуют больше ресурсов и могут приводить к дедлокам.

Конкретный пример из моей практики с PostgreSQL: У нас была очередь фоновых задач, где множество воркеров параллельно выбирали «свободные» задачи. Уровень REPEATABLE READ вызывал частые сериализационные сбои. Мы перешли на READ COMMITTED и использовали SELECT ... FOR UPDATE SKIP LOCKED для безопасного выбора задач:

BEGIN;
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;

SELECT * FROM background_jobs
WHERE status = 'pending'
ORDER BY created_at
FOR UPDATE SKIP LOCKED
LIMIT 1;

-- ... обработка задачи
UPDATE background_jobs SET status = 'processing' WHERE id = ...;

COMMIT;

Риски, которые я учитываю:

  • Неповторяющееся чтение (Non-repeatable Read): Данные могут измениться между двумя чтениями внутри одной транзакции. Это допустимо для агрегации аналитики, но не для финансовых операций.
  • Фантомное чтение (Phantom Read): Могут появиться новые строки, удовлетворяющие условию. Это критично, если логика зависит от количества строк.

Я снижаю изоляцию только для конкретных, хорошо изолированных операций, где эти аномалии не нарушают бизнес-логику.

Ответ 18+ 🔞

Да ты послушай, какая история! Вот сидишь ты, бывает, смотришь на свой код, а он тормозит, как черепаха в сиропе. И думаешь: «Ёпта, ну что за хуйня?» А оказывается, всё дело в этой самой изоляции транзакций, которая, как ревнивая баба, всё держит под замком. Так вот, снижение её уровня — это как осознанно снять с велосипеда один тормоз, чтобы быстрее с горы лететь. Да, риск есть, зато пропускная способность взлетает, а блокировок — вротберунчик!

Эти строгие уровни, REPEATABLE READ или SERIALIZABLE, они, конечно, дают предсказуемость, как немецкий автобан. Но ресурсов жрут — овердохуища, и дедлоки устраивают чаще, чем гопники в подворотне.

Вот тебе живой пример, как у нас в PostgreSQL было: Представь очередь фоновых задач. Куча воркеров носится, пытается схватить свободную задачку. На REPEATABLE READ у нас постоянно вылетали сериализационные сбои. Чувак, терпения ноль ебать! Мы взяли, перешли на READ COMMITTED и применили хитрожопый приёмчик SELECT ... FOR UPDATE SKIP LOCKED. Это как аккуратно взять печеньку с тарелки, которую никто не держит, а не вырывать её из рук у жадного ребёнка.

BEGIN;
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;

SELECT * FROM background_jobs
WHERE status = 'pending'
ORDER BY created_at
FOR UPDATE SKIP LOCKED
LIMIT 1;

-- ... обработка задачи
UPDATE background_jobs SET status = 'processing' WHERE id = ...;

COMMIT;

Но, конечно, риски-то никуда не делись, их надо в башке держать:

  • Неповторяющееся чтение: Прочитал ты данные, отвлёкся на кофе, а когда вернулся — они уже другие. Для каких-то аналитических подсчётов — да похуй. А вот если бабки считать — тут уже волнение ебать, так нельзя.
  • Фантомное чтение: Ты посчитал, что строк пять, а они тебе новую, шестую, подсунули, пока ты не видел. Если твоя логика от количества строк пляшет — это пиздец, тут уже хиросима будет.

Так что я эту изоляцию снижаю точечно, только для конкретных операций, где эти аномалии — как назойливая муха: неприятно, но бизнес-логику не сломают. А в остальном — строгость и порядок. Э, бошка, думай!