SQLAlchemy 使用連接池。這意味著可以在不同的 SQLAlchemy 會話中重復使用相同的連接。但是,單個 SQLAlchemy 會話包含在其自身中并在關閉后被丟棄。然而,連接保持“活動”。
我想使用 set_config 將某些內容保存到 Postgresql 中的資料庫會話存盤中:
PERFORM set_config('session.storage', 'remember-me-across-this-session', false)
現在,這是在資料庫會話的范圍內。我的問題是:當 SQLAlchemy 使用相同的連接創建一個新的 SQLAlchemy Session 時,這是否也會創建一個新的資料庫會話,或者該連接是否會在其整個生命周期內重復使用相同的資料庫會話?
注意:我已經嘗試通過將所有相關池大小設定為最小值(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 會話之間重置。然而,因為這是邏輯的關鍵部分,我希望得到第二意見/肯定,以確保我沒有搞砸。
uj5u.com熱心網友回復:
1. SQLAlchemy 會重置資料庫會話嗎?
不,不是的。
1.1. 關于 SQLAlchemy 會話
SQLAlchemysession.close()關閉剩余的 SQLAlchemy 事務,這些事務呼叫ROLLBACK它們的連接并將它們回傳到池中。
從如何關閉 SQLAlchemy 會話:
一個 SQLAlchemy Session 通常代表一個或多個事務的范圍,在特定的資料庫連接上。
1.2. 關于 PostgreSQL 會話
從如何找出當前 Postgres 事務的數字 ID:
會話“與 TCP 連接同義”。
1.3. 關于 PostgreSQLSET
從https://www.postgresql.org/docs/9.3/sql-set.html:
如果
SET(或等效地SET SESSION)在后來被中止的事務中發出,則SET在事務回滾時命令的效果消失。一旦周圍的事務被提交,效果將持續到會話結束,除非被另一個SET.
2. 為什么題目中的測驗有效?
在測驗中,沒有任何操作導致 Zope 將會話狀態標記為已更改。
Zopetransaction.commit()檢查會話狀態是否改變:
- 如果不是,則呼叫 SQLAlchemy
session.close()并將其對 SQLAlchemy 事務的參考設定為None。- 如1.1 所述。關于 SQLAlchemy 會話,這會呼叫
ROLLBACK連接。- 如1.3 所述。關于 PostgreSQL
SET,該SET命令的效果消失。
- 如1.3 所述。關于 PostgreSQL
- 如1.1 所述。關于 SQLAlchemy 會話,這會呼叫
- 否則,它會提交 SQLAlchemy 事務。
- 如1.3 所述。關于 PostgreSQL
SET,效果將持續到 (PostgreSQL) 會話結束。
- 如1.3 所述。關于 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')
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/336844.html
