Node.js使用mysql2时报包乱序、连接超时断开导致服务崩溃如何解决
问题根因
- MySQL服务端主动断开空闲连接:MySQL默认的
wait_timeout(非交互连接超时,默认值通常为8小时)和interactive_timeout(交互连接超时)参数控制空闲连接的存活时间,你的Node.js服务中持有的MySQL连接长时间没有请求触发,就会被服务端主动切断,客户端无感知的情况下继续复用该连接,就会触发包乱序、连接断开报错 - 未捕获连接错误事件:报错明确提示
Unhandled 'error' event,连接被断开时抛出的错误没有被监听捕获,直接导致Node.js进程崩溃
解决方案
1. 代码侧修复(优先推荐,无需修改数据库配置)
方案A:使用连接池替代单连接(生产环境标准方案)
mysql2内置的连接池会自动维护连接可用性,自动销毁失效连接、新建可用连接,参考配置如下:
const mysql = require('mysql2/promise'); const pool = mysql.createPool({ host: '数据库地址', user: '数据库用户名', password: '数据库密码', database: '业务库名', // 核心配置:连接空闲多久后自动释放,数值必须小于MySQL的wait_timeout idleTimeout: 60 * 60 * 1000, // 示例设为1小时 // 开启存活校验,自动淘汰失效连接 enableKeepAlive: true, keepAliveInitialDelay: 0 }); // 业务查询直接调用pool.execute即可 async function execQuery(sql, params) { const [rows] = await pool.execute(sql, params); return rows; }
方案B:单连接增加错误监听+自动重连(仅适合测试/低并发场景)
如果必须使用单连接,必须添加错误事件监听避免进程崩溃,同时实现断开自动重连逻辑:
const mysql = require('mysql2'); const DB_CONFIG = { // 你的数据库连接配置 }; let dbConnection; function initConnection() { dbConnection = mysql.createConnection(DB_CONFIG); // 监听错误事件,捕获断开异常自动重连 dbConnection.on('error', (err) => { if (err.code === 'PROTOCOL_CONNECTION_LOST' || err.code === '4031') { // 延迟2秒重连,避免数据库压力过大 setTimeout(initConnection, 2000); } else { throw err; } }); dbConnection.connect(); } initConnection();
2. 数据库侧调整(可选,配合代码侧使用)
修改MySQL配置文件(通常为my.cnf或my.ini),调大超时参数,修改后重启MySQL服务生效:
[mysqld] # 单位为秒,示例设为24小时 wait_timeout = 86400 interactive_timeout = 86400
验证方式
修改完成后启动服务,闲置时间超过之前的触发崩溃的空闲时长后,再发起数据库请求,确认进程无崩溃、查询正常返回即可。
内容的提问来源于stack exchange,提问作者md tareque
相关产品推荐
相关产品推荐

