在标识映射之外强制使用 sqlalchemy ORM get()
Forcing a sqlalchemy ORM get() outside identity map
背景
get()
方法在 SQLAlchemy 的 ORM 中是特殊的,因为它在向数据库发出 SQL 查询之前尝试 return 来自标识映射的对象(请参阅documentation).
这对性能有好处,但可能会导致分布式应用程序出现问题,因为一个对象可能已被另一个进程修改,因此本地进程无法知道该对象是脏的,并且会继续检索陈旧的对象当 get()
被调用时来自恒等映射。
问题
如何强制get()
忽略身份映射并每次都调用数据库?
例子
- 我在 ORM 中定义了一个
Company
对象。
- 我有一个
price_updater()
进程每秒更新所有 Company
对象的 stock_price
属性。
- 我有一个
buy_and_sell_stock()
偶尔买卖股票的流程。
- 现在,在这个过程中,我可能加载了一个
microsoft = Company.query.get(123)
对象。
- 几分钟后,我可能会发出另一个
Company.query.get(123)
的电话。从那以后股票价格发生了变化,但是我的 buy_and_sell_stock()
过程不知道变化,因为它发生在另一个过程中。
- 因此,
get(123)
从会话的身份映射中调用 return 的 Company
的陈旧版本,这是一个问题。
我搜索了 SO(在 [sqlalchemy] 标签下)并阅读了 SQLAlchemy 文档以试图找出如何做到这一点,但还没有找到方法。
使用 session.expire(my_instance)
will cause the data to be re-selected on access. However, even if you use expire
(or expunge
), the next data that is fetched will be based on the transaction isolation level. See the PostgreSQL docs on isolations levels (it applies to other databases as well) and the SQLAlchemy docs on setting isolation levels.
您可以测试实例是否在 in
的会话中:my_instance in session
.
你可以use filter
instead of get
to bypass the cache,但它仍然有相同的隔离级别限制。
Company.query.filter_by(id=123).one()
背景
get()
方法在 SQLAlchemy 的 ORM 中是特殊的,因为它在向数据库发出 SQL 查询之前尝试 return 来自标识映射的对象(请参阅documentation).
这对性能有好处,但可能会导致分布式应用程序出现问题,因为一个对象可能已被另一个进程修改,因此本地进程无法知道该对象是脏的,并且会继续检索陈旧的对象当 get()
被调用时来自恒等映射。
问题
如何强制get()
忽略身份映射并每次都调用数据库?
例子
- 我在 ORM 中定义了一个
Company
对象。 - 我有一个
price_updater()
进程每秒更新所有Company
对象的stock_price
属性。 - 我有一个
buy_and_sell_stock()
偶尔买卖股票的流程。- 现在,在这个过程中,我可能加载了一个
microsoft = Company.query.get(123)
对象。 - 几分钟后,我可能会发出另一个
Company.query.get(123)
的电话。从那以后股票价格发生了变化,但是我的buy_and_sell_stock()
过程不知道变化,因为它发生在另一个过程中。 - 因此,
get(123)
从会话的身份映射中调用 return 的Company
的陈旧版本,这是一个问题。
- 现在,在这个过程中,我可能加载了一个
我搜索了 SO(在 [sqlalchemy] 标签下)并阅读了 SQLAlchemy 文档以试图找出如何做到这一点,但还没有找到方法。
使用 session.expire(my_instance)
will cause the data to be re-selected on access. However, even if you use expire
(or expunge
), the next data that is fetched will be based on the transaction isolation level. See the PostgreSQL docs on isolations levels (it applies to other databases as well) and the SQLAlchemy docs on setting isolation levels.
您可以测试实例是否在 in
的会话中:my_instance in session
.
你可以use filter
instead of get
to bypass the cache,但它仍然有相同的隔离级别限制。
Company.query.filter_by(id=123).one()