Что такое ACID и что означает каждая буква
Что проверяют
Различаете ли вы, что гарантирует движок базы, а что обязано делать приложение. Для Python-разработчика важнее вторая половина: кто открывает транзакцию, кто её закрывает и что произойдёт, если про коммит забыли, потому что драйвер, пул соединений и ORM ведут себя по-разному.
Как отвечать
Atomicity: набор операций применяется целиком или откатывается целиком, промежуточного состояния снаружи не видно.
Consistency: после коммита соблюдены ограничения схемы, то есть первичные и внешние ключи, уникальность, CHECK. Бизнес-правило база проверит, только если оно записано ограничением.
Isolation: сколько чужой незавершённой работы видит параллельная транзакция. Это шкала уровней от READ UNCOMMITTED до SERIALIZABLE, в PostgreSQL по умолчанию READ COMMITTED, и на нём возможны неповторяемое чтение и фантомы.
Durability: подтверждённый коммит переживает падение процесса и потерю питания, потому что журнал сброшен на диск до ответа клиенту.
Дальше про инструменты:
with engine.begin() as conn: # commit на выходе, rollback при исключении
conn.execute(stmt)В SQLAlchemy единица работы это сессия: flush отправляет SQL, но транзакцию не завершает, завершает commit. Разумная граница транзакции в вебе это один запрос пользователя, а не вся жизнь сессии.
Где спотыкаются
Считают, что курсор всё сохранил сам. Драйвер sqlite3 из стандартной библиотеки открывает транзакцию перед изменяющими запросами и без явного commit теряет их при закрытии соединения.
Путают flush и commit в SQLAlchemy: после flush данные видны внутри той же транзакции и объекты получили идентификаторы, поэтому кажется, что запись прошла, хотя откат ещё всё отменит.
Держат транзакцию открытой на время внешнего HTTP-вызова или долгого расчёта. Соединение занято, блокировки не отпущены, а на SERIALIZABLE сверху добавится ошибка сериализации, которую никто не повторяет.