Как ведет себя база данных при уровне изоляции сериализуемый
Что проверяют
Понимаете ли вы, что гарантирует SERIALIZABLE и как его реализует конкретная СУБД. Сильный ответ объясняет, что транзакции идут параллельно, а база гарантирует результат, как при каком-то последовательном порядке. Следом спрашивают, что приложение делает с ошибкой сериализации.
Как отвечать
Уровень исключает грязное, неповторяемое и фантомное чтение, а также write skew, который пропускает Repeatable Read на снимках. Пример: два дежурных врача одновременно проверяют, что дежурит кто-то ещё, и оба уходят.
Механизм зависит от базы:
- PostgreSQL: Serializable Snapshot Isolation. Транзакции читают снимок и не ждут друг друга, зависимости отслеживаются предикатными блокировками
SIReadLock, которые ничего не блокируют. При опасном пересечении одна транзакция падает с SQLSTATE40001; - MySQL InnoDB: обычный
SELECTв транзакции становитсяSELECT ... FOR SHARE, работают блокировки строк и промежутков. Вместо откатов по конфликту чаще ожидания и дедлоки; - SQL Server: блокировки диапазонов ключей.
В Python уровень задают в Django через OPTIONS базы, ключ isolation_level, в SQLAlchemy параметром isolation_level="SERIALIZABLE" у движка. В psycopg ошибка приходит как SerializationFailure. Приложение обязано повторить всю транзакцию с начала: цикл вокруг transaction.atomic() или retry из tenacity с лимитом попыток.
Откатов тем больше, чем длиннее транзакции, поэтому их держат короткими. Для отчётов в PostgreSQL есть SERIALIZABLE READ ONLY DEFERRABLE.
Где спотыкаются
Говорят, что транзакции выполняются строго по одной. Параллельность сохраняется, меняется только набор допустимых результатов.
Не делают повторов. Ошибка 40001 выглядит как баг, хотя это штатное поведение уровня, и код без ретрая теряет операции.
Повторяют только упавший запрос, а не всю транзакцию. Прочитанные раньше данные уже устарели, и повтор одного UPDATE воспроизводит ту же аномалию.