Что такое транзакция и как она реализуется в Python
Что проверяют
Понимаете ли вы, что транзакция это механизм базы, и знаете ли, как ей управляют из кода.
Как отвечать
Транзакция это механизм базы данных, а не языка: несколько операций выполняются как одно целое, с гарантиями атомарности, согласованности, изоляции и долговечности. Python лишь управляет ею через соединение.
На уровне стандартного интерфейса к базам соединение по умолчанию работает в режиме, где транзакция открывается неявно, а подтверждение и откат вызываются явно. Соединение можно использовать как контекстный менеджер: успешный выход подтверждает, исключение откатывает. Важная тонкость драйвера PostgreSQL: этот контекстный менеджер управляет транзакцией, а не соединением, и по выходу соединение остаётся открытым. Многие ждут обратного и получают утечку соединений.
В SQLAlchemy работа идёт через сессию, у которой есть явный блок начала транзакции, а современный стиль предполагает контекстный менеджер.
В Django есть три уровня:
- блок атомарности как контекстный менеджер или декоратор. Вложенные блоки не создают новых транзакций, а ставят точки сохранения, к которым откатываются;
- режим транзакции на весь запрос, включаемый настройкой;
- отложенное действие после подтверждения. Это очень полезная вещь: отправку письма или постановку фоновой задачи нужно делать после фиксации, иначе задача может начать работу раньше, чем данные окажутся в базе, и не найдёт их. Классическая гонка в проектах на Django.
Общие правила, не зависящие от инструмента: транзакция должна быть короткой, внутри неё не делают обращений к внешним сервисам и не ждут пользователя, а для защиты от параллельных изменений берут либо блокировку строки при чтении, либо версию записи.
Где спотыкаются
Считают контекстный менеджер соединения закрывающим соединение.
Отправляют письма и ставят задачи внутри транзакции.
Держат транзакцию открытой на время внешнего вызова.
Не знают про точки сохранения и ждут независимых вложенных транзакций.