Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/289.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 数据库连接泄漏:PostgreSQL、SQLAlchemy、Flask_Python_Postgresql_Flask_Sqlalchemy - Fatal编程技术网

Python 数据库连接泄漏:PostgreSQL、SQLAlchemy、Flask

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

我正在运行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.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__)