SQLAlchemy и ORM
Раздел про SQLAlchemy 2.x: Core и ORM, модели через Mapped, связи, сессия и unit of work, ленивая загрузка и N+1, запросы, транзакции и блокировки, async, Alembic, производительность и грабли.
Зачем для UCP. Репозиторий и Unit of Work в Python-сервисе почти всегда стоят на SQLAlchemy, и большинство странностей «обработчик работает, а данные не те» объясняются тем, как ORM ведёт себя между
flush,commitи ленивой загрузкой. Без этой фазы обработчики команд пишут вслепую.
Одиннадцать статей, по одной теме на статью, читать лучше подряд.
Модель
- Что такое ORM и SQLAlchemy — Core и ORM, стиль 2.0, движок и пул, когда ORM помогает, а когда мешает.
- Модели и маппинг —
DeclarativeBase,Mapped, типы колонок, умолчания, ограничения и соглашения об именах. - Связи между таблицами —
relationship,back_populates, многие-ко-многим, каскады и удаление.
Сессия и загрузка
- Сессия и unit of work — состояния объекта, identity map,
flushпротивcommit,expire_on_commit. - Ленивая загрузка и N+1 — стратегии загрузки, как увидеть N+1 в логах и как его убрать.
- Запросы —
select()в стиле 2.0, соединения, агрегаты, подзапросы,text()и постраничная выборка.
Эксплуатация
- Транзакции и блокировки — границы транзакции, savepoint, уровни изоляции,
FOR UPDATE, оптимистичная версия. - Асинхронный SQLAlchemy —
AsyncSession, драйверы, greenlet, что нельзя делать в async и как это обойти. - Миграции: Alembic — автогенерация и её пределы, расширение и сжатие, запуск в выкате.
- Производительность — пул, пакетные вставки, потоковое чтение, отложенные колонки, как измерять.
- Типичные грабли —
DetachedInstanceError, сессия между задачами, autoflush, JSON без отслеживания, наивное время.