Flask-SQLAlchemy 连接池连接超出上限问题处理
Flask-SQLAlchemy 连接池连接超出上限
在 Flask 中使用 Flask-SQLAlchemy 进行数据库操作时遇到报错:sqlalchemy.exc.TimeoutError: QueuePool limit of size 10 overflow 10 reached, connection timed out, timeout 30 (Background on this error at: http://sqlalche.me/e/13/3o7r)
正常情况下,可能是高并发请求时,连接池的大小不足以处理所有的数据库请求。可以通过增加 SQLAlchemy 连接池的大小解决问题,配置项 SQLALCHEMY_POOL_SIZE 和 SQLALCHEMY_POOL_OVERFLOW 来调整池的大小。
app.config['SQLALCHEMY_POOL_SIZE'] = 20 # 增加池大小
app.config['SQLALCHEMY_POOL_OVERFLOW'] = 10 # 增加溢出连接数
app.config['SQLALCHEMY_POOL_TIMEOUT'] = 30 # 增加连接超时时间(秒)
但是,在增加池大小后仍然出现报错,经过排查发现是定义 SQLAlchemy 模型时使用的 SQLAlchemy() 对象和 Flask 应用使用的 SQLAlchemy() 对象不是同一个,导致 Flask 应用无法自动关闭连接。为了防止循环导入,在 models 文件中创建 db = SQLAlchemy() 对象,然后在 app.py 文件中导入 models 文件,解决循环导入的问题。
重新整理了一个简单的示例:
app.py - 主应用文件
from flask import Flask
from flask_migrate import Migrate
from blueprints import main_blueprint
from models import db
# 创建 Flask 应用实例
app = Flask(__name__)
# 数据库 URI
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+mysqldb://root:1234@127.0.0.1:3306/demo'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False # 禁用修改追踪
app.config['SQLALCHEMY_POOL_SIZE'] = 10 # 设置连接池大小
db.init_app(app)
# 初始化迁移
Migrate(app, db)
# 注册蓝图
app.register_blueprint(main_blueprint)
# 创建数据库
with app.app_context():
db.create_all() # 创建数据库表
if __name__ == '__main__':
app.run(port=5002, debug=True)
models.py - 数据模型文件
from flask_sqlalchemy import SQLAlchemy
# 初始化数据库实例
db = SQLAlchemy()
# 定义用户模型
class User(db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True, nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)
phone = db.Column(db.String(11), unique=True, nullable=True)
password_hash = db.Column(db.String(128), nullable=False)
def __repr__(self):
return f'<User {self.username}>'
# 定义博客文章模型
class Post(db.Model):
__tablename__ = 'posts'
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(120), nullable=False)
content = db.Column(db.Text, nullable=False)
user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
user = db.relationship('User', backref=db.backref('posts', lazy=True))
def as_dict(self):
return {c.name: getattr(self, c.name) for c in self.__table__.columns}
def __repr__(self):
return f'<Post {self.title}>'
blueprints.py - 蓝图文件
from flask import Blueprint, request, jsonify
from models import db, Post
# 创建蓝图
main_blueprint = Blueprint('main', __name__)
# 路由:主页,显示所有博客文章
@main_blueprint.route('/')
def index():
posts = Post.query.all() # 获取所有文章
return {'code': 0, 'data': {'posts': [post.as_dict() for post in posts]}}
# 路由:创建博客文章
@main_blueprint.route('/post', methods=['POST'])
def create_post():
title = request.json['title']
content = request.json['content']
new_post = Post(title=title, content=content, user_id=1) # 假设用户 ID 为 1
db.session.add(new_post)
db.session.commit()
return {'code': 0, 'data': {'new_post': new_post.as_dict()}}

浙公网安备 33010602011771号