[英]Leaking database connections: PostgreSQL, SQLAlchemy, Flask
我正在運行 PostgreSQL 9.3 和 SQLAlchemy 0.8.2 並且遇到數據庫連接泄漏。 部署應用程序后會消耗大約 240 個連接。 在接下來的 30 小時內,這個數字逐漸增加到 500,屆時 PostgreSQL 將開始斷開連接。
我使用 SQLAlchemy 線程本地會話:
from sqlalchemy import orm, create_engine
engine = create_engine(os.environ['DATABASE_URL'], echo=False)
Session = orm.scoped_session(orm.sessionmaker(engine))
對於 Flask Web 應用程序,在請求拆卸期間發送對Session
代理對象的.remove()
調用:
@app.teardown_request
def teardown_request(exception=None):
if not app.testing:
Session.remove()
這應該與Flask-SQLAlchemy
所做的相同。
我還有一些循環運行的周期性任務,我為循環的每次迭代調用.remove()
:
def run_forever():
while True:
do_stuff(Session)
Session.remove()
我做錯了什么可能導致連接泄漏?
如果我從SQLAlchemy的實驗中正確記起,則使用scoped_session()
創建可以從多個位置訪問的會話。 也就是說,您可以在一種方法中創建會話,然后在另一種方法中使用它,而無需顯式傳遞會話對象。 它通過保留會話列表並將它們與“作用域ID”相關聯來實現。 默認情況下,要獲取作用域ID,它將使用當前線程ID; 因此每個線程都有會話。 您可以提供一個scopefunc
以提供(例如)每個請求一個ID:
# This is (approx.) what flask-sqlalchemy does:
from flask import _request_ctx_stack as context_stack
Session = orm.scoped_session(orm.sessionmaker(engine),
scopefunc=context_stack.__ident_func__)
另外,請注意有關執行后台任務的其他答案和評論。
首先,這是運行后台任務的一種非常糟糕的方法。 嘗試像芹菜一樣的任何ASync調度程序。
不能100%確定,所以根據提供的信息有點猜測,但是我想知道每個頁面加載是否正在啟動一個新的數據庫連接,該數據庫隨后正在監聽通知。 如果是這種情況,我想知道數據庫連接是否已從池中有效刪除,並因此在下一頁加載時創建。
如果是這種情況,我的建議是讓一個單獨的DBI數據庫句柄專用於偵聽通知,以使這些通知在隊列中不活動。 這可以在工作流程之外完成。
也
特別是,在同時發出多個請求時,就會發生泄漏。 同時,我可以看到一些請求未完成查詢執行並超時。 您可以編寫一些內容來自己管理。
通過在@app.teardown_request
調用@app.teardown_request
sqlalchemy.engine.Engine.dispose()
解決了類似的問題
在此處查看我的問題: Web 請求后未刪除 SQLAlchemy 數據庫會話
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.