Короткий ответ
flush() отправляет накопленные изменения в БД в рамках текущей транзакции, делая их видимыми для последующих запросов этой же транзакции (например, чтобы получить сгенерированный id), но не фиксирует их навсегда; commit() выполняет flush неявно и затем фиксирует транзакцию, делая изменения постоянными и видимыми другим транзакциям.
Как это работает подробнее
SQLAlchemy Session накапливает изменения объектов в памяти (unit of work) и не отправляет их в БД немедленно при каждом session.add(); flush синхронизирует состояние объектов с БД, но до commit всё это можно откатить через rollback().
Пример кода
example.py
with Session(engine) as session:
author = Author(name="Jane Doe")
session.add(author)
session.flush() # author.id уже доступен, но транзакция ещё не зафиксирована
book = Book(title="New Book", author_id=author.id)
session.add(book)
session.commit() # фиксирует и author, и book одной транзакциейЧто использовать на практике
- Практика. Явный flush() нужен, когда в рамках одной транзакции нужно получить автоматически сгенерированный PK нового объекта до завершения всей бизнес-операции; в большинстве сценариев достаточно одного commit() в конце.
Подводные камни
- Ошибка. Вызывают commit() слишком часто внутри одной логической операции, фиксируя промежуточные состояния, которые должны быть атомарны вместе с последующими шагами; путают flush с commit, считая, что после flush rollback уже не отменит изменения — это не так.