即使设置了SQLALCHEMY_POOL_RECYCLE,Flask-SQLAlchemy也不会自动回收MySQL连接

问题描述 投票:0回答:1

最近我的flask程序遇到了

Lost connection to MySQL server during query
的错误。我搜索了一些文档和讨论。看来是MySQL超时断开了连接,但是flask并没有回收这些过期的连接。
我目前正在使用
Flask_SQLAlchemy==2.4.4
。从flask 2.x的文档中了解到,设置SQLALCHEMY_POOL_RECYCLE可以调整flask回收过期连接的时间。我尝试设置它,但它没有解决我的问题。
这是我的演示:

import time

import sqlalchemy as sql
from flask import Flask
from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()


class TestData(db.Model):
    id = sql.Column(sql.BigInteger, primary_key=True)

def create_app() -> Flask:
    app: Flask = Flask(__name__)
    app.config["SQLALCHEMY_DATABASE_URI"] = "mysql+pymysql://mysql_host"
    app.config["SQLALCHEMY_POOL_SIZE"] = 1
    app.config["SQLALCHEMY_POOL_RECYCLE"] = 3
    db.init_app(app)
    return app


def test():
    app = create_app()
    with app.app_context():
        q1 = TestData.query.get(0)
        print(q1)
        time.sleep(10)
        q2 = TestData.query.get(1)
        print(q2)

test()

我运行

SET GLOBAL wait_timeout = 8;
将MySQL断开连接时间设置为8秒,并且还配置了
app.config["SQLALCHEMY_POOL_RECYCLE"] = 3
time.sleep(10)
之后,q2的查询仍然失败。

套装版

SQLAlchemy==1.3.22
Flask_SQLAlchemy==2.4.4
Flask==1.1.2
python flask sqlalchemy flask-sqlalchemy
1个回答
0
投票

来自设置池回收的文档:

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

您的第一个

.get()
检查连接、开始事务并发出 SELECT 查询。由于您没有完成事务,因此连接保持“打开”状态(保持签出状态),10 秒后您尝试再次使用同一连接。

修复方法是在第一个

.get()
之后完成事务,以便连接返回到池中。 10 秒后,您的下一个
.get()
将检查连接并将被回收。

        q1 = TestData.query.get(0)
        print(q1)
        db.session.rollback()  # complete the transaction
        time.sleep(10)
        q2 = TestData.query.get(1)
        print(q2)
© www.soinside.com 2019 - 2024. All rights reserved.