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
相关产品推荐
相关产品推荐

