Flask+MariaDB后端Flutter应用多用户访问时Web服务响应缓慢问题排查求助
解决Flask+MariaDB并发请求下响应时间暴涨的问题
嘿,这个问题我之前帮朋友排查过类似的——你现在遇到的根本问题是每次请求都手动创建和销毁数据库连接,这在并发场景下会直接拖垮性能!咱们来拆解下原因,再给出具体的解决办法:
为什么并发时响应时间暴跌?
数据库创建连接是个开销很大的操作:要完成TCP握手、权限验证、资源分配等一系列步骤。单用户请求时,这个开销不明显,但当多个请求同时进来,数据库要同时处理大量连接创建请求,加上MariaDB默认的连接数限制,会导致请求排队等待可用连接,响应时间自然从毫秒级涨到十几秒。
最优解决方案:使用数据库连接池
连接池的核心思路是提前创建一批数据库连接并复用,避免每次请求都重复创建销毁。Flask生态里有两种常用的实现方式:
方式1:用SQLAlchemy自带连接池(推荐,整合更方便)
SQLAlchemy是Flask常用的ORM框架,自带成熟的连接池管理,不用自己手动维护。步骤如下:
- 先安装依赖:
pip install sqlalchemy pymysql
- 重构你的代码,让SQLAlchemy管理连接:
from flask import Flask, request, jsonify from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker app = Flask(__name__) # 初始化数据库引擎,自带连接池,参数可根据并发量调整 # 格式:mysql+pymysql://用户名:密码@主机:端口/数据库名 engine = create_engine( 'mysql+pymysql://your_user:your_password@localhost:3306/your_db', pool_size=10, # 连接池常驻连接数 max_overflow=20 # 峰值时允许的额外临时连接数 ) # 创建会话工厂,用于获取数据库连接 SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) # 定义获取数据库会话的工具函数 def get_db(): db = SessionLocal() try: yield db finally: db.close() @app.route('/ws_name', methods=['GET']) def ws_name(): # 从连接池获取一个连接会话 db = next(get_db()) try: param = request.args.get('param') # 执行查询(这里替换成你的实际SQL) query_result = db.execute( "SELECT * FROM your_table WHERE your_param = :param", {"param": param} ).fetchall() # 把查询结果转成JSON友好的格式 result = [dict(row) for row in query_result] except Exception as e: # 这里可以加日志记录错误,方便排查 return jsonify({"error": str(e)}), 500 return jsonify(result), 200
方式2:用DBUtils独立连接池(适合不想用ORM的场景)
如果你不想引入ORM,DBUtils是专门做数据库连接池的工具库,用法也很简单:
- 安装依赖:
pip install DBUtils pymysql
- 重构代码:
from flask import Flask, request, jsonify from DBUtils.PooledDB import PooledDB import pymysql app = Flask(__name__) # 初始化连接池 db_pool = PooledDB( creator=pymysql, # 指定连接驱动 maxconnections=15, # 连接池最大连接数 mincached=2, # 初始化时保持的空闲连接数 host='localhost', user='your_user', password='your_password', database='your_db', port=3306 ) @app.route('/ws_name', methods=['GET']) def ws_name(): # 从连接池获取连接(注意:这里close是放回池,不是真销毁) cnx = db_pool.connection() cursor = None try: param = request.args.get('param') cursor = cnx.cursor() cursor.execute("SELECT * FROM your_table WHERE your_param = %s", (param,)) # 把结果转成字典 columns = [desc[0] for desc in cursor.description] result = [dict(zip(columns, row)) for row in cursor.fetchall()] except Exception as e: return jsonify({"error": str(e)}), 500 finally: if cursor: cursor.close() cnx.close() # 将连接放回连接池 return jsonify(result), 200
额外优化建议
- 调整MariaDB连接数限制:登录MariaDB执行
SHOW VARIABLES LIKE 'max_connections';,如果当前值太小(比如默认151),可以根据你的并发量调整,比如改成500(注意不要超过服务器内存承载能力)。 - 优化SQL查询:检查你的查询语句是否有索引缺失,比如
function_execute_many_query里的查询,如果是全表扫描,并发时会大幅增加数据库负载。可以用EXPLAIN分析查询语句。 - 添加请求日志:记录每个请求的响应时间、数据库操作耗时,方便后续定位性能瓶颈。
内容的提问来源于stack exchange,提问作者user1111
相关产品推荐
相关产品推荐

