我有一个使用SQLAlchemy访问PostgreSQL数据库的Flask Web应用程序.
当我启动应用程序时,会立即在PostgreSQL中创建一个"in transaction"连接.
当应用程序使用一段时间后,其中一些连接出现在pg_stat_activity中.
一段时间后,似乎在某些资源上发生了死锁,我必须重新启动应用程序以使其再次运行.
我已经读过,如果我在关闭数据库会话之前从使用数据库的视图函数返回,则会发生这种情况.所以为了避免这个问题,我创建了以下装饰器:
@app.teardown_appcontext
def shotdown_session(exception=None):
db.session.remove()
Run Code Online (Sandbox Code Playgroud)
这应该导致在每次请求之后关闭所有会话,并有效地避免出现"在事务中"连接的问题.
不幸的是,它似乎没有任何影响.
那么,我该如何解决这个问题呢?
更新:
我应该补充一点,我已经验证我的装饰器功能实际上已经运行了.我通过添加打印来验证这一点:
@app.teardown_appcontext
def shotdown_session(exception=None):
print "@app.teardown_appcontext: shotdown_session()"
db.session.remove()
Run Code Online (Sandbox Code Playgroud)
我还通过向视图函数添加打印来验证它确实在返回视图函数后运行:
[...]
products = db.session.query(...).all()
print "BEFORE RETURN"
return render_template("show_products.html", products=products)
Run Code Online (Sandbox Code Playgroud)
这会产生如下日志行:
* 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 -
Run Code Online (Sandbox Code Playgroud)
我还浏览了代码,并在使用db.session在每个函数中返回之前添加了一个db.session.remove()调用.这确实摆脱了in事务,但是,它也会导致问题.我将SQLAlchemy模型对象从数据库传递给模板.然后,一些模板对这些模型对象执行某些操作,导致应用程序失败,因为该对象不再附加到会话.
编辑2014-12-08:
可以在此处看到连接设置:
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, scoped_session
from flask_sqlalchemy import SQLAlchemy
from config import cfg
engine …Run Code Online (Sandbox Code Playgroud)