You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flask+SQLAlchemy删除MySQL记录请求倍增引发QueuePool溢出问题

问题根因

你遇到的问题由前后端两个错误共同导致:

  1. 前端事件重复绑定:每次datatables表格重绘(比如删除后刷新列表)时,都重复给删除按钮注册了点击事件回调,没有解绑旧事件,导致点击一次按钮触发N次删除请求,N等于历史删除次数+1,对应你日志里每次删除的请求数线性递增的表现。
  2. 后端数据库连接泄漏:原生SQLAlchemy的session管理逻辑错误,手动调用close、remove的时机不对,加上你之前用Flask-SQLAlchemy的方式不正确,导致数据库连接没有正常释放,请求量上来后直接打满连接池,抛出QueuePool超限错误。

可行解决方案

第一步:修复前端事件绑定问题(必须先修,否则请求数还是会递增)

优先用事件委托的方式绑定点击事件,只需要页面初始化时绑定一次,不需要每次表格重绘重复绑定:

// 页面初始化时仅执行一次,不要放到datatables的drawCallback回调内
$(document).on('click', '.你的删除按钮类名', function() {
  const blogId = $(this).data('你存博客id的自定义属性名')
  // 原有删除请求逻辑
  $.post(`/backend/blog/delete/${blogId}`, function(res) {
    if (res.status) {
      // 成功后刷新datatables
    }
  })
})

如果必须把绑定逻辑放到drawCallback里,每次绑定前先解绑旧事件:

function drawCallback() {
  $('.你的删除按钮类名').off('click').on('click', function() {
    // 原有删除逻辑
  })
}

第二步:修复后端session管理问题,推荐直接用标准Flask-SQLAlchemy用法:

1. 修正入口文件__init__.py配置

import os
from flask import Flask
from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

def create_app():
    app = Flask(__name__)
    app.config['SQLALCHEMY_DATABASE_URI'] = os.getenv('SQLALCHEMY_DATABASE_URI')
    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
    # 连接池配置可按需调整
    app.config['SQLALCHEMY_POOL_SIZE'] = 10
    app.config['SQLALCHEMY_MAX_OVERFLOW'] = 20
    db.init_app(app)

    # 注册你的蓝图
    from .你的蓝图模块名 import blueprint
    app.register_blueprint(blueprint, url_prefix='/backend/blog')

    # 初始化表结构要在app上下文内执行
    with app.app_context():
        db.create_all()
    
    return app

2. 修正Blog模型代码

from datetime import datetime
from 你的项目入口模块名 import db
# 注意User模型也要同步改为继承db.Model

class Blog(db.Model):
    __tablename__ = 'blog'

    id = db.Column(db.Integer(), primary_key=True)
    author_id = db.Column(db.String(255), nullable=False)
    title = db.Column(db.String(255), nullable=False, unique=True)
    content = db.Column(db.String(255), nullable=False)
    # 注意:default传函数引用不要加括号,否则时间只会在模块加载时计算一次
    created_at = db.Column(db.DateTime(), default=datetime.now)
    updated_at = db.Column(db.DateTime(), default=datetime.now, onupdate=datetime.now)

    def collect_data_serverside(self, request):
        DATA = []
        # 原有sessionDB替换为db.session
        query = db.session.query(User, Blog).filter(User.id==Blog.author_id)
        for u, b in query.all():
            DATA.append({'A': b.id, 'B': u.nombre, 'C': b.title, 'D': b.created_at})
        columns = table_schemas.BLOG
        return ServerSideTable(request, DATA, columns, True, True, 'backend.blog', 'C', 'table_blogposts').output_result()

    @staticmethod
    def delete(id):
        db.session.query(Blog).filter(Blog.id == id).delete()
        db.session.commit()
        # 不需要手动调用close/remove,Flask-SQLAlchemy会自动在请求结束后回收连接

额外说明

如果不想改用Flask-SQLAlchemy,要继续用原生SQLAlchemy的话,只需要做两个修改:

  • 在蓝图中绑定请求结束钩子,统一回收session:
@blueprint.teardown_request
def remove_session(exception=None):
    sessionDB.remove()
  • 删除Blog.delete方法里的sessionDB.close()和sessionDB.remove()两行,不要手动处理session回收。

内容的提问来源于stack exchange,提问作者Berkeley Now

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 22:36:02