我有一個使用SQLAlchemy訪問PostgreSQL數據庫的Flask Web應用程序。Flask和SQLAlchemy在PostgreSQL的事務連接中導致大量IDLE
當我啓動應用程序時,PostgreSQL中立即創建了一個「in transaction」連接。
當應用程序使用一段時間後,其中幾個連接出現在pg_stat_activity中。
經過一段時間後,似乎在某些資源上發生死鎖,並且我必須重新啓動應用程序才能使其再次運行。
我讀過,如果我在關閉數據庫會話之前從使用數據庫的視圖函數返回,可能會發生這種情況。因此,爲了避免這個問題,我創建了以下裝飾:
@app.teardown_appcontext
def shotdown_session(exception=None):
db.session.remove()
這應當引起所有會話的每個請求之後被關閉,有效地避免「在交易」的連接問題。
不幸的是,它似乎沒有任何效果。
那麼,我該如何真正解決這個問題呢?
UPDATE:
我也許應該補充一點,我已經驗證了我的裝飾功能的實際運行。 我證實了這一通過增加打印到它:
@app.teardown_appcontext
def shotdown_session(exception=None):
print "@app.teardown_appcontext: shotdown_session()"
db.session.remove()
我也驗證了它確實之後進行查看函數返回運行通過添加打印到視圖功能,以及:
[...]
products = db.session.query(...).all()
print "BEFORE RETURN"
return render_template("show_products.html", products=products)
這產生日誌行這樣的:
* Running on http://0.0.0.0:5000/
* Restarting with reloader
BEFORE RETURN
@app.teardown_appcontext: shotdown_session()
10.0.0.100 - - [03/Dec/2014 13:41:30] "GET /product/51 HTTP/1.1" 200 -
我還通過代碼去,並使用db.session加入db.session.remove()調用中的每個函數的每個返回前。 這確實消除了在交易中,但是,它也會導致問題。我將SQLAlchemy模型對象從數據庫傳遞到模板。有些模板會對這些模型對象執行一些操作,導致應用程序失敗,因爲對象不再附加到會話中。
EDIT 2014年12月8日:
連接建立在這裏可以看到:
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, scoped_session
from flask_sqlalchemy import SQLAlchemy
from config import cfg
engine = create_engine(cfg["db_uri"], echo=False, pool_size=10)
db = SQLAlchemy()
Base = db.Model
Session = scoped_session(sessionmaker(bind=engine))
整個應用程序的結構可在這裏找到:http://paste.yt/p3219.html
你的sqlalchemy引擎或連接代碼是什麼樣的?你是否在做任何與自動提交或其他選項類似的東西? – aezell 2014-12-05 20:59:36
我已經添加上面的SQL引擎設置。爲了顯示應用程序的整個結構,我還添加了相關文件的exerpts。如果您對我所做的事情有任何一般性意見或改進,請讓我知道:) – Thomas 2014-12-08 10:45:25
您是否在使用任何pooling for postgres本身,比如pgbouncer或其他?將這樣的工具與SQLAlchemy的池合併在一起會導致類似這樣的奇怪連接問題。 – aezell 2014-12-08 16:14:42