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

Flask并发调用API时MySQL连接不可用及服务崩溃问题求助

问题根源与解决方案

核心问题

你遇到的"MySQL Connection not available"和段错误,本质是全局共享单个MySQL连接导致的并发冲突。Flask默认多线程运行,多个请求同时操作同一个数据库连接时,会打乱连接的状态,引发连接不可用甚至底层内存错误(段错误)。


解决方案

1. 改用数据库连接池管理连接

不要全局创建单个连接,用连接池为每个请求分配独立连接,用完自动归还。

修改config/db_connect.py:

import mysql.connector
from mysql.connector import pooling

# 创建连接池,pool_size根据你的并发量调整(建议10-20)
db_pool = mysql.connector.pooling.MySQLConnectionPool(
    pool_name="attendance_pool",
    pool_size=15,
    host="localhost",
    user="root",
    passwd="******",
    database="usersdb"
)

在API中获取/释放连接(以mark_attendence为例):

@attendance.route('/groups/mark_attendence', methods=['POST', 'GET'])
def mark_attendence():
    now = datetime.datetime.now()
    # ... 图片处理等逻辑保持不变 ...
    
    # 从连接池获取连接
    mysql = db_pool.get_connection()
    cursor1 = mysql.cursor()
    try:
        if len(array_findFaces) > 0:
            for i in array_findFaces:
                if(i['text'] != 'Unknown'):
                    # 用参数化查询,避免SQL注入
                    cursor1.execute(
                        "UPDATE usersdb.sessions SET status = 1 WHERE status = 0 AND sessionid = %s AND uid = %s;",
                        (str(session_id), str(student[1]))
                    )
        else: 
            print("----------------No face detected----------------")
        mysql.commit()
    except Exception as e :
        print("exception in mark attendance")
        print(e)
        mysql.rollback()  # 异常时回滚事务
    finally:
        cursor1.close()
        mysql.close()  # 归还连接到池
    
    # 后续查询同样从连接池拿连接
    mysql = db_pool.get_connection()
    cursor2 = mysql.cursor()
    try:
        cursor2.execute(
            "SELECT name, pic, status, usersdb.sessions.updated_at, uid, email FROM usersdb.user JOIN usersdb.sessions ON usersdb.user.id = usersdb.sessions.uid WHERE usersdb.sessions.sessionid = %s;",
            (str(session_id),)
        )
        data = cursor2.fetchall()
    finally:
        cursor2.close()
        mysql.close()
    
    # ... 剩余逻辑保持不变 ...

2. 修复SQL注入漏洞

你的代码直接拼接SQL字符串,存在严重安全风险,还可能引发语法错误。所有SQL操作必须用参数化查询,比如mark_by_uid修改:

@attendance.route('/groups/markbyuid', methods=['POST'])
def mark_by_uid():
    uid = request.get_json()['uid']
    status = request.get_json()['status']
    sessionId = request.get_json()['sessionId']
    
    mysql = db_pool.get_connection()
    cursor = mysql.cursor()
    try:
        cursor.execute(
            "UPDATE usersdb.sessions SET status = %s WHERE uid = %s AND sessionid = %s;",
            (str(status), str(uid), str(sessionId))
        )
        mysql.commit()
    except Exception as e:
        print('exception is here ')
        print(e)
        mysql.rollback()
    finally:
        cursor.close()
        mysql.close()
    
    return flask.jsonify({'data': 'success'}) 

3. 确保资源正确释放

用finally块保证无论是否发生异常,游标和连接都会被关闭(归还到池),避免连接泄漏导致连接池耗尽。

4. 生产环境使用专业服务器

默认的Werkzeug服务器仅适合开发,生产环境建议用Gunicorn或uWSGI,配置合适的worker和线程数,比如:

gunicorn --workers=4 --threads=5 app:app

(worker数建议等于CPU核心数,线程数根据并发量调整)

5. 检查MySQL连接限制

查看MySQL的max_connections参数,确保连接池的pool_size不超过该值(默认一般为151),避免无法创建新连接。


内容的提问来源于stack exchange,提问作者Question hunter

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 19:05:30