Об обновлении объектов в сеансе sqlalchemy

Ну, я имею дело с сомнением в sqlalchemy и освежающих объектах!

Я в ситуации, в которой у меня есть 2 сеанса, и один и тот же объект был запрошен в обеих сессиях!... Для некоторых вещей я не могу закрыть одну из сессий. Я изменил объект и совершил изменения в сеансе A, но в сеансе B атрибуты являются исходными! без изменений!..

Итак... я должен внедрить какую-то систему уведомлений для обмена сообщениями или есть встроенный способ сделать это в sqlalchemy??

Ответ 1

Сеансы предназначены для работы следующим образом. Атрибуты объекта в сеансе B будут содержать то, что было при первом запросе в сеансе B. Кроме того, SQLAlchemy не будет пытаться автоматически обновлять объекты в других сеансах, когда они меняются, и я не думаю, что было бы разумно попытаться создать что-то как это.

Вы должны активно думать о продолжительности жизни каждого сеанса как одной транзакции в базе данных. Как и когда сеансы должны иметь дело с тем, что их объекты могут быть устаревшими, это не техническая проблема, которая может быть решена с помощью алгоритма, встроенного в SQLAlchemy (или любого расширения для SQLAlchemy): это "бизнес-проблема", решение которой вы должны определять и кодировать себя. "Правильный" ответ может заключаться в том, чтобы сказать, что это не проблема: логика, возникающая в сеансе B, может быть действительной, если она использовала данные в то время, когда начался сеанс B. Ваша "проблема" на самом деле не может быть проблемой. Документы фактически имеют весь раздел о том, когда использовать сеансы, но он дает довольно мрачный ответ, если вы надеетесь на решение одного размера для всех..

Сессия обычно строится в начале логического где доступ к базе данных потенциально ожидается.

Сессия, всякий раз, когда она используется для связи с базой данных, начинает транзакции базы данных, как только она начнет общаться. Предполагая флаг autocommit остается по умолчанию по умолчанию False, это транзакция продолжается до тех пор, пока сеанс не будет откат, совершенным или закрытым. Сессия начнет новую транзакцию, если она используется снова, после окончания предыдущей транзакции; из из этого следует, что сеанс способен иметь продолжительность жизни по многим транзакциям, хотя и по одному за раз. Мы ссылаемся на эти две концепции как область транзакций и область сеанса.

Здесь подразумевается, что ORM SQLAlchemy поощряет разработчик, чтобы установить эти две области в своем заявлении, в том числе не только когда начинается и заканчивается область действия, но и пространство этих областей, например, если один экземпляр сеанса будет локальным к потоку выполнения внутри функции или метода, если это глобальный объект, используемый всем приложением, или где-то посередине эти два.

Бремя, устанавливаемое разработчиком для определения этой области, является одной областью где ORM SQLAlchemy обязательно имеет сильное мнение о том, как необходимо использовать базу данных. Единица работы шаблона одна из которых накапливает изменения со временем и периодически промывает их, сохраняя состояние памяти в синхронизации с тем, что, как известно, присутствует в локальная транзакция. Этот шаблон эффективен только тогда, когда он имеет смысл области транзакций.

Тем не менее, есть несколько вещей, которые вы можете сделать, чтобы изменить ситуацию:

Во-первых, вы можете сократить время ожидания сеанса. Сессия B запрашивает объект, а затем вы делаете что-то с этим объектом (в том же сеансе), что вы хотите, чтобы атрибуты были обновлены. Одним из решений является выполнение этой второй операции в отдельном сеансе.

Другим является использование методов expire/refresh, поскольку docs показывают...

# immediately re-load attributes on obj1, obj2
session.refresh(obj1)
session.refresh(obj2)

# expire objects obj1, obj2, attributes will be reloaded
# on the next access:
session.expire(obj1)
session.expire(obj2)

Вы можете использовать session.refresh(), чтобы немедленно получить обновленную версию объекта, даже если сеанс уже запросил объект раньше.