2014-12-03 84 views
6

我有一個使用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

+0

你的sqlalchemy引擎或連接代碼是什麼樣的?你是否在做任何與自動提交或其他選項類似的東西? – aezell 2014-12-05 20:59:36

+0

我已經添加上面的SQL引擎設置。爲了顯示應用程序的整個結構,我還添加了相關文件的exerpts。如果您對我所做的事情有任何一般性意見或改進,請讓我知道:) – Thomas 2014-12-08 10:45:25

+0

您是否在使用任何pooling for postgres本身,比如pgbouncer或其他?將這樣的工具與SQLAlchemy的池合併在一起會導致類似這樣的奇怪連接問題。 – aezell 2014-12-08 16:14:42

回答

3

I」當您在Debug mode中運行Flask時,已經看到了這種情況。如果你的代碼拋出一個異常並且調試器開始運行,事務將永遠不會被「回滾」或「移除」。因此,失敗請求上使用的會話永遠不會返回到池中。

解決方法是禁用調試模式。

+0

我在調試和非調試模式下都得到了這個結果。 – Thomas 2015-03-23 10:54:46

+0

您是否嘗試過使用最新的Flask-SQLAlchemy模塊?看起來你使用的是舊版本。看看代碼中的這一點,看看它會自動爲你做什麼:https://github.com/mitsuhiko/flask-sqlalchemy/blob/master/flask_sqlalchemy/__init__.py#L807 – 2015-03-23 18:22:24

+0

我會盡力回覆 – Thomas 2015-03-27 13:49:03