Даже если установлен SQLALCHEMY_POOL_RECYCLE, Flask-SQLAlchemy не будет автоматически перерабатывать соединения MySQL

Недавно моя программа 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 есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
0
52
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Из документации по Setting Pool Recycle:

Обратите внимание, что аннулирование происходит только во время извлечения, а не для каких-либо соединений, которые находятся в извлеченном состоянии.

Ваш первый .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)

Другие вопросы по теме