首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何避免使用烧瓶-SQLAlchemy的QueuePool限制错误?

如何避免使用烧瓶-SQLAlchemy的QueuePool限制错误?
EN

Stack Overflow用户
提问于 2022-01-07 18:32:09
回答 3查看 2.2K关注 0票数 2

我正在使用Flask和Postgre开发一个get应用程序,然后在我的网页中有一个下拉列表,它是从select到DB填充的,在选择了几次不同的值之后,我得到了"sqlalchemy.exc.TimeoutError:“。

我的包裹的版本如下:

代码语言:javascript
运行
复制
Flask-SQLAlchemy==2.5.1
psycopg2-binary==2.8.6
SQLAlchemy==1.4.15

我的DB连接参数设置为:

代码语言:javascript
运行
复制
app.config['SQLALCHEMY_POOL_SIZE'] = 20
app.config['SQLALCHEMY_MAX_OVERFLOW'] = 20
app.config['SQLALCHEMY_POOL_TIMEOUT'] = 5
app.config['SQLALCHEMY_POOL_RECYCLE'] = 10

我得到的错误是:

代码语言:javascript
运行
复制
sqlalchemy.exc.TimeoutError: QueuePool limit of size 20 overflow 20 reached, connection timed out, timeout 5.00 (Background on this error at: https://sqlalche.me/e/14/3o7r)

在将“SQLALCHEMY_MAX_OVERFLOW”的值从20更改为100之后,在下拉列表中发生一些值更改后,将得到以下错误。

代码语言:javascript
运行
复制
psycopg2.OperationalError: connection to server at "localhost" (::1), port 5432 failed: FATAL:  sorry, too many clients already

每次从下拉列表中选择一个新值时,都会向数据库触发四个查询,并使用它们在我的HTML中填充四个对应的表,其中包含来自该查询的结果。

在对DB的每个查询之后,我都有一个'db.session.commit()‘语句,但是即使我有它,在对我的下拉列表进行一些值更改之后,我也会得到这个错误。

我知道我应该正确地管理我的连接会话,但我对此很不放心。我考虑将池超时设置为5s,而不是默认的30秒,希望会话将以更快的方式关闭并返回池,但这似乎没有帮助。

作为@snakecharmerb的建议,我检查了以下内容的输出:

代码语言:javascript
运行
复制
select * from pg_stat_activity;

在webapp显示错误之前,我运行了10个不同的值,这意味着使用的所有20+20会话都处于“空闲事务”状态。

有没有人知道我该换什么或找什么?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2022-01-10 12:13:05

在StackOverFlow的另一篇文章中,我找到了解决我所面临的问题的方法。

当您将烧瓶应用程序分配给db变量时,在指示应该使用哪个flask应用程序的基础上,您还可以传递会话选项,如下所示:

代码语言:javascript
运行
复制
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy(app, session_options={'autocommit': True})

“自动提交”的用法解决了我的问题。

现在,正如建议的那样,我正在使用:

代码语言:javascript
运行
复制
app.config['SQLALCHEMY_POOL_SIZE'] = 1
app.config['SQLALCHEMY_MAX_OVERFLOW'] = 0

现在一切都正常运转了。

帮助我的最初的帖子是:Autocommit in Flask-SQLAlchemy

@snakecharmerb,@jorzel,@J_H ->,谢谢你的帮助!

票数 1
EN

Stack Overflow用户

发布于 2022-01-08 18:07:41

你在泄露连接。

稍微有点反直觉,你可能会发现你得到了更好的结果与较低的池限制。对于您正在执行的简单的单数据库查询,给定的python线程只需要一个池连接。将限制设置为1,加上0溢出,将导致您更早地注意到一个泄漏的连接。这使我们更容易将责任归咎于泄露它的源代码。目前,您有大量的代码,并且错误被推迟到发出了许多查询之后,这使得对系统行为的推理变得更加困难。我假设您使用sqlalchemy 1.4.29。

要避免泄漏,请使用以下方法:

代码语言:javascript
运行
复制
from contextlib import closing
from sqlalchemy import create_engine, text
from sqlalchemy.orm import scoped_session, sessionmaker

engine = create_engine(some_url, future=True, pool_size=1, max_overflow=0)
get_session = scoped_session(sessionmaker(bind=engine))
...
with closing(get_session()) as session:
    try:
        sql = """yada yada"""
        rows = session.execute(text(sql)).fetchall()
        session.commit()
        ...
        # Do stuff with result rows.
        ...
    except Exception:
        session.rollback()
票数 2
EN

Stack Overflow用户

发布于 2022-11-04 08:23:55

我用的是烧瓶-restful。因此,当我得到大小为20溢出20的-> QueuePool限制时,连接超时,超时5.00 (此错误的背景为:https://sqlalche.me/e/14/3o7r)

我在日志中发现我的已检出的连接没有关闭。这是我用logger.info(db_session.get_bind().pool.status())发现的

代码语言:javascript
运行
复制
def custom_decorator(error_message, db_session):
    def api_decorator(func):
        def api_request(self, *args, **kwargs):
            try:
                response = func(self)
                db_session.commit()
                return response
            except Exception as err:
                db_session.rollback()
                logger.error(error_message.format(err))
                return error_response(
                message=f"Internal Server Error",
                status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
                )
            finally:
                db_session.close()
        return api_request

    return api_decorator

因此,我不得不创建这个装饰器,它自动处理db_session关闭。使用这一点,我不会得到任何主动检查的连接。

您可以在您的功能中使用装饰器,如下所示:

代码语言:javascript
运行
复制
@custom_decorator("blah", db_session)
def example():
    "some code"
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70625689

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档