SQLAlchemy 是不是从同一连接重置 SQLAlchemy 会话之间的数据库会话?
Posted
技术标签:
【中文标题】SQLAlchemy 是不是从同一连接重置 SQLAlchemy 会话之间的数据库会话?【英文标题】:Does SQLAlchemy reset the database session between SQLAlchemy Sessions from the same connection?SQLAlchemy 是否从同一连接重置 SQLAlchemy 会话之间的数据库会话? 【发布时间】:2021-11-15 04:24:32 【问题描述】:SQLAlchemy 利用连接池。这意味着可以在不同的 SQLAlchemy 会话中重用相同的连接。但是,单个 SQLAlchemy 会话包含在其自身中,并在关闭后被丢弃。但是,连接保持“活动”。
我想使用 set_config 将一些内容保存到 Postgresql 中的数据库会话存储中:
PERFORM set_config('session.storage', 'remember-me-across-this-session', false)
现在,这是在数据库会话的范围内。我的问题是:当 SQLAlchemy 使用相同的连接创建一个新的 SQLAlchemy 会话时,这是否也会创建一个新的数据库会话,或者连接会在其生命周期内重复使用相同的数据库会话吗?
注意: 我已经尝试通过将所有相关池大小设置为最小值(max_overflow 0、pool_size 1、pool_recycle 600)然后运行以下脚本(简化)来测试这一点:
print(DBSESSION.execute(text("SELECT set_config('session.storage', 'remember-me-across-this-session', false)")).first())
print(DBSESSION.execute(text("SELECT current_setting('session.storage')")).first())
transaction.commit()
DBSESSION.close()
for _ in range(5):
print(DBSESSION.execute(text("SELECT current_setting('session.storage')")).first())
transaction.commit()
DBSESSION.close()
此测试没有“记住”循环中后续会话的第一行中设置的值,因此确认数据库会话确实在同一连接的 SQLAlchemy 会话之间重置。然而,因为这是逻辑的关键部分,我希望得到第二个意见/肯定,以确保我没有搞砸。
【问题讨论】:
【参考方案1】:1。 SQLAlchemy 是否重置数据库会话?
不,它没有。
1.1。关于 SQLAlchemy 会话
SQLAlchemy session.close()
关闭剩余的 SQLAlchemy 事务,这些事务在其连接上调用 ROLLBACK
并将它们返回到池中。
来自How to close a SQLAlchemy session:
SQLAlchemy 会话通常表示在特定数据库连接上一个或多个事务的范围。
1.2。关于 PostgreSQL 会话
来自How do I find out the numeric ID of the current Postgres Transaction:
会话是“TCP 连接的同义词”。
1.3。关于PostgreSQLSET
来自https://www.postgresql.org/docs/9.3/sql-set.html:
如果在稍后中止的事务中发出
SET
(或等效的SET SESSION
),则在回滚事务时,SET
命令的效果会消失。提交周围事务后,效果将持续到会话结束,除非被另一个SET
覆盖。
2。为什么问题中的测试有效?
在测试中,没有任何操作导致 Zope 将会话状态标记为已更改。
Zope transaction.commit()
检查会话状态是否改变:
session.close()
并将其对 SQLAlchemy 事务的引用设置为 None
。
如 1.1 中所述。关于 SQLAlchemy 会话,这会在连接上调用 ROLLBACK
。
如 1.3 中所述。关于PostgreSQL SET
,SET
命令的效果消失了。
否则,它会提交 SQLAlchemy 事务。
如 1.3 中所述。关于 PostgreSQL SET
,效果将持续到(PostgreSQL)会话结束。
您可以通过将会话显式标记为已更改来验证 Else
案例:
print(DBSESSION.execute(text("SELECT set_config('session.storage', 'remember-me-across-this-session', false)")).first())
print(DBSESSION.execute(text("SELECT current_setting('session.storage')")).first())
mark_changed(DBSESSION.registry()) # Add this
transaction.commit()
注意:由于transaction.commit()
和transaction.abort()
已经隐式调用session.close()
,随后对DBSESSION.close()
的调用实际上什么都不做。
3。如何重置会话运行时参数?
为sqlalchemy.events.PoolEvents.checkin
添加一个事件监听器并调用RESET
。
@event.listens_for(engine, 'checkin')
def receive_checkin(dbapi_connection, connection_record):
cursor = dbapi_connection.cursor()
cursor.execute('RESET session.storage')
# cursor.execute('RESET ALL')
【讨论】:
很好的答案。非常感谢!以上是关于SQLAlchemy 是不是从同一连接重置 SQLAlchemy 会话之间的数据库会话?的主要内容,如果未能解决你的问题,请参考以下文章