关于在sqlalchemy会话中刷新对象

时间:2013-10-02 17:43:41

标签: python mysql session notifications sqlalchemy

好吧,我正在处理有关sqlalchemy和物品刷新的疑问!

我遇到的情况是我有2个会话,并且在两个会话中都查询了相同的对象!...对于某些特定的事情,我无法关闭其中一个会话。 我修改了对象并在会话A中提交了更改,但在会话B中,属性是最初的属性!没有修改!..

那么......我应该实现某种通知系统来传达变化,还是有一种内置的方法来实现这一点?

4 个答案:

答案 0 :(得分:29)

Sessions are designed to work like this。会话B中对象的属性将保留在会话B中首次查询时的对象。此外,SQLAlchemy在更改时不会尝试自动刷新其他会话中的对象,也不认为尝试创建某些对象是明智的像这样。

您应该积极地将每个会话的生命周期视为数据库中的单个事务。会话如何以及何时需要处理其对象可能过时的事实并不是一个技术问题,可以通过SQLAlchemy(或SQLAlchemy的任何扩展)中内置的算法来解决:这是一个“业务”问题,您必须解决它的问题确定并编码自己。 “正确”的响应可能是说这不是问题:如果在会话B启动时使用了数据,则会话B发生的逻辑可能是有效的。你的“问题”实际上可能不是问题。文档实际上有一个entire section on when to use sessions,但如果你希望获得一个通用的解决方案,那么它会给你一个非常严峻的反应......

  

会话通常在逻辑的开头构建   可能预期数据库访问的操作。

     

会话,无论何时用于与数据库通信,都会开始   数据库事务一开始通信。假设   autocommit标志保留其建议的默认值False,这个   在会话回滚之前,事务仍在进行中,   承诺或关闭。如果会话,会话将开始新的交易   在前一个交易结束之后再次使用;从   因此,会话能够延长寿命   跨越许多交易,虽然一次只有一个。我们指的是这些   作为事务范围和会话范围的两个概念。

     

这里的含义是SQLAlchemy ORM正在鼓励   开发人员在他或她的应用程序中建立这两个范围,   不仅包括范围的开始和结束,还包括范围   这些范围的例子,例如,单个Session实例应该是本地的   如果它是一个函数或方法中的执行流程   整个应用程序使用的全局对象,或介于两者之间的某个位置   这两个。

     

开发商确定此范围的负担是一个方面   SQLAlchemy ORM必然对如何有强烈意见   应该使用数据库。工作单元格式具体   随着时间的推移累积变化并定期冲洗,   保持内存状态与已知的存在状态同步   本地交易。这种模式只有在有意义时才有效   交易范围已到位。

也就是说,你可以采取一些措施来改变现状:

首先,您可以减少会话保持打开的时间。会话B正在查询对象,之后您正在使用该对象(在同一会话中)执行某些操作,以使属性保持最新。一种解决方案是在单独的会话中完成第二个操作。

另一种方法是使用expire / refresh方法,如docs show ...

# 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()立即获取对象的最新版本,即使会话早先已经查询过该对象。

答案 1 :(得分:3)

运行此命令,强制会话从您选择的数据库中更新最新值:

session.expire_all()

Excellent DOC about default behavior and lifespan of session

答案 2 :(得分:1)

我只是遇到了这个问题,现有的解决方案由于某种原因对我不起作用。起作用的是调用session.commit()。调用该对象后,该对象具有数据库中的更新值。

答案 3 :(得分:0)

TL; DR而不是进行会话同步,而是查看是否可以在不使用(多个)会话的情况下直接在引擎上使用SQLAlchemy Core语法合理地轻松地编码您的任务

对于具有SQL和JDBC经验的人来说,了解SQLAlchemy至关重要的一件事,不幸的是,我几个月来都没有清楚地阅读多个文档,因为SQLAlchemy包含两个根本不同的部分:核心和ORM。由于ORM文档首先在网站上列出,并且大多数示例都使用类似ORM的语法,因此如果要考虑使用SQL / JDBC来考虑ORM,就会被人投入使用并自行设置错误和混乱。 ORM使用其自己的抽象层来完全控制实际SQL语句的执行方式和时间。经验法则是,创建和销毁会话很便宜,并且永远不要将其重新用于程序流程和逻辑中可能导致重新查询,同步或多线程的任何事物。另一方面,核心是直接的无刺激的SQL,非常类似于JDBC驱动程序。在docs中,我发现使用Core over ORM的“建议”:

鼓励在此处直接在Connection上进行简单的SQL操作,例如增加计数器或在日志中插入额外的行 表。在处理连接时,期望使用核心级SQL 将使用操作;例如SQL表达式语言教程中介绍的内容。

尽管如此,看来使用Connection会产生与使用Session相同的副作用:对特定记录的重新查询将返回与第一个查询相同的结果,即使数据库中记录的内容已更改也是如此。因此,显然,Connections与Sessions一样“不可靠”,以“实时”读取DB内容,但是直接Engine执行似乎很好,因为它从池中选择了一个Connection对象(假定检索到的Connection永远不会在其中相对于查询而言,相同的“重用”状态与特定的打开连接有关)。根据SA文档

,应明确关闭Result对象