SQLAchemy ORM移除会话Session里的对象实例
def expunge_all(self) -> None:
"""Remove all object instances from this ``Session``.
This is equivalent to calling ``expunge(obj)`` on all objects in this
``Session``.
"""
all_states = self.identity_map.all_states() + list(self._new)
self.identity_map._kill()
self.identity_map = identity.WeakInstanceDict()
self._new = {}
self._deleted = {}
statelib.InstanceState._detach_states(all_states, self)
方法会彻底清空当前会话,移除所有跟踪的对象(包括新添加的、已存在的和标记为删除的),使会话回到初始空状态。这在需要完全重置会话而不关闭它时很有用;这不会影响数据库中的数据,只是从会话的跟踪中移除这些对象
分离后的对象不再受会话管理(如不再自动同步到数据库)
测试环境重置
在单元测试中,每个测试用例可能需要一个干净的会话状态
在
setUp()
或tearDown()
中调用可以确保测试隔离
批量操作后的清理
当执行完大批量数据操作后,需要释放内存但保留会话继续使用
比关闭并重新创建会话更高效
长时间运行会话的维护
对于长时间保持打开的会话(如 web 应用的请求周期)
定期清理可以防止内存泄漏和性能下降
安全敏感操作前
在处理敏感数据前清空会话,确保没有残留对象
例如权限变更或关键业务操作前
调试和开发
当需要调查会话状态问题时
可以强制清空会话观察行为变化
复杂事务管理
在多阶段事务处理中,阶段间需要清除对象状态
但保持数据库连接活跃
注意:与 close()
不同,expunge_all()
后会话仍可用,只是变成了空容器。适合需要保持会话打开但清除所有跟踪对象的场景。
In the most general sense, the Session
establishes all conversations with the database and represents a “holding zone” for all the objects which you’ve loaded or associated with it during its lifespan. It provides the interface where SELECT and other queries are made that will return and modify ORM-mapped objects. The ORM objects themselves are maintained inside the Session
, inside a structure called the identity map - a data structure that maintains unique copies of each object, where “unique” means “only one object with a particular primary key”.从最一般的意义上讲,Session
建立与数据库的所有对话,并代表在其生命周期内加载或与之关联的所有对象的 “保持区”。它提供了一个接口,用于进行 SELECT 和其他查询,这些查询将返回和修改 ORM 映射的对象。 ORM 对象本身维护在Session
内部,在一个称为身份映射的结构中 - 一个维护每个对象的唯一副本的数据结构,其中“唯一”意味着“只有一个具有特定主键的对象”。
The Session
in its most common pattern of use begins in a mostly stateless form. Once queries are issued or other objects are persisted with it, it requests a connection resource from an Engine
that is associated with the Session
, and then establishes a transaction on that connection. This transaction remains in effect until the Session
is instructed to commit or roll back the transaction. When the transaction ends, the connection resource associated with the Engine
is released to the connection pool managed by the engine. A new transaction then starts with a new connection checkout.Session
Session 在其最常见的使用模式中以 mostlyless 形式开始。一旦发出查询或保留其他对象,它就会从与 Session
关联的 Engine
请求连接资源,然后在该连接上建立事务。此事务一直有效,直到指示 Session
提交或回滚事务。 当 transactionend 结束时,与 Engine 关联的连接资源被释放到由 Engine
管理的连接池中。 然后,newtransaction 以新的 connection checkout 开始。
The ORM objects maintained by a Session
are instrumented such that whenever an attribute or a collection is modified in the Python program, a change event is generated which is recorded by the Session
. Whenever the database is about to be queried, or when the transaction is about to be committed, the Session
first flushes all pending changes stored in memory to the database. This is known as the unit of work pattern.由 Session
维护的 ORM 对象经过检测,因此每当在 Python程序中修改属性或集合时,都会生成一个由Session
记录的更改事件。 每当要查询数据库或即将提交事务时,Session
首先将存储在内存中的所有待处理更改刷新到数据库中。这称为 Unit of work 模式。
When using a Session
, it’s useful to consider the ORM mapped objects that it maintains as proxy objects to database rows, which are local to the transaction being held by the Session
. In order to maintain the state on the objects as matching what’s actually in the database, there are a variety of events that will cause objects to re-access the database in order to keep synchronized. It is possible to “detach” objects from a Session
, and to continue using them, though this practice has its caveats. It’s intended that usually, you’d re-associate detached objects with another Session
when you want to work with them again, so that they can resume their normal task of representing database state.当使用 Session
时,将 ORM 映射对象视为代理对象维护到数据库行是很有用的,这些对象是 Session
持有的事务的本地对象。 为了保持对象上的状态与数据库中的实际状态匹配,有各种事件将导致对象重新访问数据库以保持同步。 可以从Session
中 “分离” 对象,并继续使用它们,尽管这种做法有其注意事项。 通常,当你想再次使用它们时,你会将分离的对象与另一个 Session
重新关联,以便它们可以恢复表示数据库状态的正常任务。
https://groups.google.com/g/sqlalchemy/c/twoHzgXcR60/m/nZqMKkCz9UwJ?pli=1
why the expire_all() exists?
The purpose is to remove any database-loaded state from all current objects so that the next access of any attribute, or any query execution, will retrieve new state, freshening those objects which are still referenced outside of the session with the most recent available state. It is called automatically upon commit() or rollback() assuming an autocommit=False session, so that when the transaction, and its isolated environment, come to an end, subsequent accesses of those objects will acquire new data from whatever other transactions were committed subsequent to the previous transaction. expire_all() itself is useful when:
目的是从所有当前对象中删除任何数据库加载的状态,以便任何属性的下一次访问或任何查询执行都将检索新状态,用最新的可用状态刷新那些仍在会话之外引用的对象。它在假设自动提交=错误会话的提交()或回滚()时自动调用,以便当事务及其隔离环境结束时,这些对象的后续访问将从上一个事务之后提交的任何其他事务中获取新数据。expire_all()本身在以下情况下很有用:
- the session is used in autocommit=True mode, and new changes from other transactions are desired.
-会话在自动提交=True模式下使用,需要来自其他事务的新更改。
- against a database that does not support transactions, or perhaps within a weakly isolated transaction, again to load changes from other transactions or connections.
-针对不支持事务的数据库,或者可能在弱隔离事务中,再次加载来自其他事务或连接的更改。
- when SQL statements have been executed against the current transaction using execute() which may have changed significant portions of loaded state on the database.
-当SQL语句针对当前事务执行时,它可能已经改变了数据库上加载状态的重要部分。
> Shouldn't it be always better to expunge_all() instead? If it is expired, at the use of the instance another query would be issued to reattach it anyway, so why keep "useless" instances in the identity map (maybe i'm wrong about this fact, i dont know exactly how the identity map works).
>expunge_all()不应该总是更好吗?如果它过期了,在使用实例时,无论如何都会发出另一个查询来重新附加它,所以为什么要在身份映射中保留“无用”实例(也许我对这个事实是错误的,我不知道身份映射到底是如何工作的)。
They're not useless at all if you are performing operations upon them which span the scope of multiple transactions, or have any of the above use cases, and don't wish to re-establish a full graph of objects in memory. In-memory objects are essentially proxy objects to an underlying database transaction. The Session mediates this relationship.
如果您正在对它们执行跨越多个事务范围的操作,或者具有上述任何用例,并且不希望在内存中重新建立对象的完整图,那么它们根本没有用。内存中的对象本质上是底层数据库事务的代理对象。Session调解这种关系。
评论区