簡體   English   中英

泄漏的數據庫連接:PostgreSQL、SQLAlchemy、Flask

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM