Программирование SQLТранзакции и конкурентный доступРазработчик серверных приложений и баз данных

От чего зависит, что одинаково названный уровень изоляции даёт разное наблюдаемое поведение в разных СУБД?

От чего зависит, что одинаково названный уровень изоляции даёт разное наблюдаемое поведение в разных СУБД?

Проходите собеседования с ИИ помощником Hintsage

Краткий ответ

Название уровня изоляции задаёт набор минимальных гарантий, но не описывает полностью внутренний механизм СУБД. Поэтому одинаковый уровень может реализовываться через блокировки, MVCC или их комбинацию и фактически обеспечивать более сильное поведение, чем требуется стандартом.

Исторический контекст

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

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

Постановка проблемы

Разработчик может выбрать, например, READ COMMITTED и ожидать одинакового поведения во всех системах. На практике одна СУБД может блокировать чтение изменяемой строки, другая — вернуть последнюю подтверждённую версию, а третья — использовать настраиваемый режим версионного чтения.

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

Подробное решение

Есть три основных источника различий.

  1. Модель конкурентного доступа. В блокирующей реализации чтение может ждать незавершённую запись. В MVCC чтение обычно получает подходящую подтверждённую версию и не блокирует автора изменения. При этом операции записи всё равно могут конфликтовать.

  2. Граница снимка. Снимок может создаваться для каждого оператора или один раз на всю транзакцию. Поэтому повторный запрос в рамках одного уровня может увидеть новые подтверждённые изменения либо продолжить работать с прежним снимком.

  3. Дополнительные гарантии реализации. СУБД вправе предотвращать больше аномалий, чем минимально требуется уровнем. Например, в PostgreSQL READ UNCOMMITTED фактически работает как READ COMMITTED: грязные чтения не разрешаются. В других системах поведение чтения на этом уровне может быть связано с конкретной моделью блокировок.

Даже одно название REPEATABLE READ нельзя интерпретировать без уточнения реализации. В одной СУБД оно основано на фиксированном снимке, в другой может использовать блокировки или дополнительные проверки. Отдельно нужно изучать поведение SELECT, UPDATE, блокирующих чтений, внешних ключей, уникальных ограничений и сериализуемого режима.

Практическое правило: уровень изоляции выбирают по требуемой гарантии, а затем проверяют документацию конкретной СУБД. Интеграционные тесты должны включать конкурентные сценарии, потому что последовательные тесты не показывают различия между реализациями.

Ситуация из практики

Сервис отчётности перенесли с СУБД, где READ COMMITTED использовал блокирующие чтения, на СУБД с версионным чтением. После миграции отчёты перестали ждать обновления и стали выполняться быстрее, но некоторые отчёты начали собирать данные из разных состояний базы между отдельными операторами.

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

Выбрали точечное решение: для отчётов, которым нужен единый снимок, использовали транзакцию с подходящей семантикой снимка, а для коротких операций оставили READ COMMITTED. Поведение подтвердили конкурентными тестами для целевой СУБД. Это сохранило производительность и явно закрепило требуемую гарантию вместо зависимости от названия уровня.

Что кандидаты часто упускают

  1. Вопрос: означает ли одинаковый уровень изоляции одинаковый набор блокировок?

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

  1. Вопрос: может ли реализация быть сильнее заявленного уровня?

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

  1. Вопрос: достаточно ли проверить уровень изоляции в одной транзакции?

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