【问题标题】:Connection pool recycle in SQLAlchemy does not recycle idle stated connections from pg_stat_activitySQLAlchemy 中的连接池回收不会从 pg_stat_activity 回收空闲的声明连接
【发布时间】:2021-12-21 00:22:25
【问题描述】:

我有一个 Flask 应用程序,它使用 SQLAlchemy 作为其 ORM 和 PostgreSQL 作为数据库管理系统进行 insertselectupdate 查询。最小的工作示例是:

import config as cfg
from flask import Flask
from extensions import db


flask_app = Flask(__name__)
flask_app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
flask_app.config['SQLALCHEMY_DATABASE_URI'] = cfg.POSTGRES_DB_CONNECT
flask_app.config['SQLALCHEMY_ENGINE_OPTIONS'] = {"pool_pre_ping": True,
                                                 "pool_recycle": 600}
flask_app.secret_key = cfg.SECRET_KEY

db.init_app(flask_app)

if __name__=="__main__":
    app.run()

如您所见,pool_recycle 参数设置为 600,因此它可以关闭超过 10 分钟的连接。但是,当我检查我的 pg_stat_activity 时,它显示了长达 2 小时的空闲状态连接。我使用这个查询来检查 pg_stat_activity

SELECT * FROM pg_stat_activity WHERE client_addr='my_service_hostname' ORDER BY query_start DESC;

我不明白为什么这些查询保留为空闲状态,并且在查询开始后 10 分钟内没有消失。也许我的错误在于我对连接池的工作方式知之甚少。有没有办法在 10 分钟内关闭连接?

更新 1:这是我使用任何查询的视图函数的最小工作示例:

import config as cfg
import os
from flask import request
from models.document import Document
from app import flask_app, ps_work
from extensions import db
from file_processors import common, documents

@flask_app.route("/files/<string:uuid>", methods=['POST'])
def upload(uuid):
    file = request.files['file']
    file_uuid = uuid.lower()
    if file:
        filename = common.Secure_Filename(request.form.get('name', file.filename)).secure_filename()
        db_file = Document(file_uuid, filename)
        db.session.add(db_file)
        db.session.commit()

        # HERE I DO SOME UPDATE
        while not ps_work.check_file_exists(os.path.join(path,filename)):
            file_vault_file_path = db_file.upload_file(path, filename)
        db.session.commit()

        # HERE I ALSO DO SOME UPDATE
        db_file.extract_text(filename)
        db_file.sooner_update(extension)
        db.session.commit()

我的错误是否有可能是使用 db.session.commit 3 次,而不是使用 db.session.flush 2 次和 db.session.commit 在最后?

【问题讨论】:

    标签: python postgresql flask sqlalchemy flask-sqlalchemy


    【解决方案1】:

    我对 Pool 的详细信息没有太多经验,但文档表明只有在请求时才会回收连接。因此,如果没有使用大量连接,则连接可能会持续超过回收限制。你能描述一下用法吗?

    https://docs.sqlalchemy.org/en/14/core/pooling.html#setting-pool-recycle

    请注意,失效仅在结帐期间发生 - 而不是在任何 处于签出状态的连接。

    【讨论】:

    • 以及如何使用它们,你不知道吗?我将更新我的问题以说明如何使用我的查询。
    • 我的意思是有很多请求通过您正在查看的服务器?或者服务器是否空闲了一段时间(即测试服务器)?如果没有发出新请求,则不会检出连接,因此不需要回收连接。还是您在生产中观察到这一点?
    • @adekability 您还收到任何错误/异常吗?或者只是想知道为什么他们的连接没有关闭?
    • 1.是的,我确实在生产中观察到了这一点。有很多请求。
    • 2.我收到此错误 (psycopg2.DatabaseError) SSL SYSCALL 错误:连接超时]
    【解决方案2】:

    实际上,我似乎还没有正确理解连接池的工作原理。我的解决方案是将NullPool 类设置为pool_class 参数为flask_app.config['SQLALCHEMY_ENGINE_OPTIONS']

    【讨论】:

      猜你喜欢
      • 2015-12-23
      • 2010-11-25
      • 2014-12-04
      • 1970-01-01
      • 1970-01-01
      • 2011-11-13
      • 2018-10-15
      • 2012-09-25
      • 1970-01-01
      相关资源
      最近更新 更多