3 回答

TA貢獻1772條經驗 獲得超5個贊
首先,您不應在connect()
函數中重復創(chuàng)建引擎。在通常的做法是有一個單一的全球Engine
每個數據庫URL例如在應用程序中。Session
由所創(chuàng)建的類也是如此sessionmaker()
。
上下文管理器到底對連接和會話做了什么?關閉會話并配置連接還是什么?
您已經對其進行編程了,如果還不清楚,請閱讀有關上下文管理器的一般信息。在這種情況下,如果在with語句控制的塊內引發(fā)了異常,它將提交或回滾會話。這兩個操作都將會話使用的連接返回到池(在您的情況下為)NullPool
,因此僅關閉了連接。
為什么在“ connect”方法中沒有NullPool作為poolclass的情況下,第一個有效的代碼示例作為問題的示例?
和
from sqlalchemy.pool import NullPool # does not work without NullPool, why?
如果沒有NullPool
引擎,您會反復創(chuàng)建池連接,因此,如果由于某種原因它們沒有超出范圍,或者它們的引用計數沒有被清零,那么即使會話返回它們,它們也將保留連接。在第二個示例中,尚不清楚會話是否及時超出范圍,因此它們也可能會保持連接。
為什么在第一個示例中,對于所有查詢,我只有一個到db的連接,但是在第二個示例中,對于每個查詢,我都有單獨的連接?(如果我理解不對,請更正我,正在使用“ pgbouncer”進行檢查)
第一個示例由于使用可以正確處理事務的上下文管理器和結束了連接的關閉NullPool
,因此該連接返回到保鏢器,該保鏢器是另一個池層。
第二個示例可能永遠不會關閉連接,因為它缺少事務處理,但是由于給出的示例,目前尚不清楚。它還可能會保留您創(chuàng)建的單獨引擎中的連接。
問題集的第4點已在“會話基礎”中的正式文檔中進行了介紹,尤其是“何時構造會話,何時提交會話以及何時關閉會話?”。和“會話線程安全嗎?” 。
有一個例外:腳本的多個實例。您不應該在進程之間共享引擎,因此,為了在它們之間共享連接,您需要一個外部池,例如PgBouncer。

TA貢獻1883條經驗 獲得超3個贊
上下文管理器到底對連接和會話做了什么?關閉會話并配置連接還是什么?
Python中的上下文管理器用于創(chuàng)建與該with語句一起使用的運行時上下文。簡單來說,當您運行代碼時:
with session_scope() as session:
entity = session.query(SomeEntity).first()
session是產生的會話。因此,對于您的上下文管理器如何處理連接和會話的問題,您要做的就是查看之后發(fā)生了yield什么,看看會發(fā)生什么。在這種情況下,它只是:
try:
yield session
session.commit()
except:
session.rollback()
raise
如果您沒有觸發(fā)任何異常,它將為session.commit(),根據SQLAlchemy文檔,它將“刷新未決的更改并提交當前事務。”
為什么在“ connect”方法中沒有NullPool作為poolclass的情況下,第一個有效的代碼示例作為問題的示例?
該poolclass參數只是告訴SQLAlchemy使用哪個子類Pool。但是,如果您通過NullPool此處,則是在告訴SQLAlchemy不要使用池。傳入時,您實際上是在禁用池連接NullPool。從文檔中:“要禁用池,請改為將poolclass設置為NullPool?!?我不能肯定地說,但使用NullPool可能會助您max_connection一臂之力。
為什么在第一個示例中,對于所有查詢,我只有一個到db的連接,但是在第二個示例中,對于每個查詢,我都有單獨的連接?(如果我理解不對,請更正我,正在使用“ pgbouncer”進行檢查)
我不太確定。我認為這與在第一個示例中如何使用上下文管理器有關,因此with塊中的所有內容都將使用session生成器。在第二個示例中,您創(chuàng)建了一個函數,該函數將初始化新的函數Session并返回它,因此您無需找回生成器。我還認為這與您的NullPool使用有關,它可以防止連接池。對于NullPool每個查詢,執(zhí)行都是自己獲取一個連接。
當您對多個偵聽腳本的腳本實例(或腳本中的單獨線程)使用SQLAlchemy和PostgreSQL DB時,打開和關閉連接(和/或與Session一起使用)的最佳實踐是什么,這是最佳做法,這些實例偵聽請求并必須分別與每個會話進行會話?(我的意思是原始SQLAlchemy而不是Flask-SQLAlchemy或類似的東西)
請參閱會話線程安全嗎?為此,但是您需要對并發(fā)采取“不共享”方法。因此,在您的情況下,您需要腳本的每個實例在彼此之間不共享任何內容。
您可能想查看使用引擎和連接。如果并發(fā)是您正在從事的工作,那么我不希望將會議弄得一團糟。那里有關于NullPool和并發(fā)的更多信息:
對于使用os.fork系統(tǒng)調用的多進程應用程序,例如Python多處理模塊,通常需要為每個子進程使用單獨的Engine。這是因為引擎維護了對連接池的引用,該連接池最終引用了DBAPI連接-這些連接往往無法跨進程邊界移植。配置為不使用池化的引擎(通過使用NullPool來實現)不具有此要求。
添加回答
舉報