最近我的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
来自设置池回收的文档:
请注意,失效仅发生在签出期间 - 不会发生在任何处于签出状态的连接上。
您的第一个
.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)