Python 数据库连接泄漏:PostgreSQL、SQLAlchemy、Flask
我正在运行PostgreSQL 9.3和SQLAlchemy 0.8.2,并遇到数据库连接泄漏的问题。部署后,应用程序将消耗大约240个连接。在接下来的30小时内,这个数字逐渐增加到500,届时PostgreSQL将开始删除连接 我使用SQLAlchemy: 对于Flask web应用程序,在请求拆卸期间发送对Python 数据库连接泄漏:PostgreSQL、SQLAlchemy、Flask,python,postgresql,flask,sqlalchemy,Python,Postgresql,Flask,Sqlalchemy,我正在运行PostgreSQL 9.3和SQLAlchemy 0.8.2,并遇到数据库连接泄漏的问题。部署后,应用程序将消耗大约240个连接。在接下来的30小时内,这个数字逐渐增加到500,届时PostgreSQL将开始删除连接 我使用SQLAlchemy: 对于Flask web应用程序,在请求拆卸期间发送对会话代理对象的.remove()调用: @app.teardown_request def teardown_request(exception=None): if not app
会话
代理对象的.remove()
调用:
@app.teardown_request
def teardown_request(exception=None):
if not app.testing:
Session.remove()
这应该与炼金术相同
我还有一些在循环中运行的定期任务,我为循环的每次迭代调用.remove()
:
def run_forever():
while True:
do_stuff(Session)
Session.remove()
我做错了什么可能导致连接泄漏?首先,运行后台任务是一种非常糟糕的方式。尝试任何异步调度程序,如芹菜 不是100%确定,所以根据提供的信息,这有点猜测,但我想知道是否每个页面加载都会启动一个新的db连接,然后该连接会侦听通知。如果是这种情况,我想知道数据库连接是否有效地从池中删除,从而在下一页加载时创建 如果是这种情况,我的建议是使用一个单独的DBI数据库句柄专门侦听通知,以便这些通知在队列中不处于活动状态。这可能在您的工作流程之外完成 也
特别是,当同时发出多个请求时,会发生泄漏。同时,我可以看到一些请求没有完成查询执行和超时。您可以自己编写一些东西来管理它。如果我在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__)
另外,请注意关于执行后台任务的其他回答和评论。应用程序是如何部署的?还要注意,从0.9开始,有
\u app\u ctx\u stack
,这在大多数情况下更合适。
# 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__)