Почему нельзя использовать scoped cache в SQLAlchemy?
Что проверяют
Понимаете ли вы, что у сессии SQLAlchemy есть карта объектов, но это часть единицы работы внутри транзакции, а не кэш. Вопрос проверяет умение отличать границы сессии от кэширования данных.
Как отвечать
Сначала снимите путаницу в терминах: отдельной возможности с таким названием в библиотеке нет. Есть scoped_session, привязка сессии к области видимости, по умолчанию к потоку, и есть identity map внутри сессии, которая держит уже загруженные объекты по первичному ключу. Именно её ошибочно называют кэшем.
Почему она не годится на эту роль:
- карта живёт внутри транзакции. Объект в открытой сессии повторно не читается, и после чужого коммита вы продолжаете видеть старое состояние, пока не сделаете
expire,refreshили не закроете сессию; - от повторного SQL спасает только выборка по первичному ключу через
session.get. Любой другой запрос уходит в базу, карта лишь вернёт тот же объект в памяти; - при долгой жизни сессия растёт: объекты удерживаются ссылками, память не освобождается, а открытая транзакция держит снимок данных.
Отсюда правило: сессия живёт ровно столько, сколько запрос или задача, и закрывается в конце. В асинхронном коде привязка к потоку неверна вовсе, областью должна быть задача, для чего у async_scoped_session есть параметр scopefunc.
Настоящее кэширование делают снаружи: отдельное хранилище с явным ключом и явной инвалидацией. Встроен здесь кэш компиляции запросов, а это про сборку SQL, а не про повторное чтение данных.
Где спотыкаются
Держат одну глобальную сессию на всё приложение. Данные протухают, память течёт, а параллельные обращения дают невоспроизводимые ошибки: сессия не потокобезопасна.
Второе: не учитывают expire_on_commit. После коммита атрибуты помечены протухшими, и следующее обращение к полю молча делает новый запрос, а вне сессии падает ошибкой отсоединённого объекта.
Третье: путают пул соединений с кэшем данных. Пул экономит установку соединения и на актуальность строк не влияет никак, так что ссылка на него в ответе про кэш выдаёт неразобранную тему.