Транзакции и изоляция: где чаще всего ломают продакшен и как этого не делать
Коллеги, давайте разберем план выполнения. Транзакция — это не «обернул в BEGIN и стало безопасно», а набор компромиссов между согласованностью, блокировками и пропускной способностью. Чем выше уровень изоляции, тем меньше сюрпризов для данных, но тем охотнее система начинает ждать, конфликтовать и душить параллелизм.
Базовая схема простая:
— Read Uncommitted: грязные чтения, в продакшене почти всегда лишний риск.
— Read Committed: нормальный дефолт для большинства CRUD-сценариев, но фантомы и неповторяемые чтения никуда не деваются.
— Repeatable Read: защищает от изменений уже прочитанных строк, зато повышает шанс на блокировки.
— Serializable: максимальная логическая защита, но по факту часто самый дорогой режим по I/O и ожиданиям.
Посмотрим, что тут с I/O в реальности. Проблема обычно не в самом уровне изоляции, а в том, что транзакция живет слишком долго: внутри нее читают лишнее, ходят во внешние сервисы, ждут пользователя, делают batch-обработку. В итоге блокировка висит дольше, чем нужно, а соседние запросы начинают строиться в очередь. Золотое правило: сначала мониторинг, потом индексы.
Практика такая: держите транзакции короткими, выносите внешние вызовы наружу, не смешивайте отчеты и OLTP в одном режиме без необходимости, а при конфликтных сценариях проверяйте не только deadlock, но и рост lock wait. В продакшене так лучше не делать, и вот почему: большинство «магических» проблем с изоляцией оказываются проблемами дизайна запроса и времени удержания блокировки.
Если нужен стабильный результат — сначала уменьшайте длительность транзакции, потом уже поднимайте изоляцию. Схема простая, но дьявол кроется в статистике.
Оптимизация производительности баз
@database_performance_tuning_arb
Транзакции и изоляция: где чаще всего ломают продакшен и как этого не делать
Этот пост опубликован в Telegram-канале Оптимизация производительности баз. Подписаться можно по ссылке: @database_performance_tuning_arb.