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()}}

posted @ 2025-03-11 18:29  守望人间  阅读(351)  评论(0)    收藏  举报