Node.js MySQL生产环境频繁出现errno:-104(ECONNRESET)错误求助
Node.js + MySQL 频繁出现 ECONNRESET 错误的排查与解决
ECONNRESET 错误本质是TCP连接被MySQL服务器主动重置,通常是连接超时、资源不足或网络问题导致的,以下是具体的排查方向和解决建议:
一、检查MySQL服务器配置
- 空闲连接超时设置:查看
wait_timeout和interactive_timeout参数,这两个值控制MySQL自动断开空闲连接的时间。如果Node.js的连接空闲时间超过这个阈值,就会触发连接重置。执行以下命令查看:
根据业务场景调整(比如设置为3600秒),修改时可以在MySQL配置文件(SHOW VARIABLES LIKE '%timeout%';my.cnf或my.ini)中添加:
重启MySQL生效。wait_timeout = 3600 interactive_timeout = 3600 - 连接数上限:检查
max_connections是否达到上限,导致新连接被拒绝。执行:
如果当前连接数接近上限,要么调大SHOW VARIABLES LIKE 'max_connections'; SHOW STATUS LIKE 'Threads_connected';max_connections,要么优化Node.js的连接池配置减少并发连接。 - 查看MySQL错误日志:在Linux系统通常是
/var/log/mysql/error.log,Windows则在MySQL安装目录的data文件夹下。查找Aborted connection相关日志,能直接看到连接断开的具体原因。
二、优化Node.js客户端配置
- 正确使用连接池并监听错误:如果用的是连接池,必须监听
error事件,防止未捕获错误导致进程崩溃。示例配置:const mysql = require('mysql'); // 建议替换为mysql2 const pool = mysql.createPool({ host: '你的MySQL地址', user: '用户名', password: '密码', database: '数据库名', connectionLimit: 10, // 不要超过MySQL的max_connections waitForConnections: true, queueLimit: 0 }); // 关键:监听连接池错误,避免进程退出 pool.on('error', (err) => { console.error('连接池错误:', err); // ECONNRESET错误通常是连接已断开,连接池会自动重建连接,无需额外处理 }); - 单个连接的错误处理:如果没有用连接池,手动创建的连接必须监听
error事件,断开时自动重建:let connection; function initConnection() { connection = mysql.createConnection({ /* 配置 */ }); connection.connect((err) => { if (err) { console.error('连接失败,2秒后重试:', err); setTimeout(initConnection, 2000); return; } connection.on('error', (err) => { console.error('连接出错:', err); if (err.fatal) { initConnection(); // 致命错误,重建连接 } }); }); } initConnection(); - 升级到mysql2模块:你当前使用的
mysql模块已停止维护,mysql2是其继任者,修复了大量连接相关的bug,性能也更好。安装命令:
代码中只需替换npm install mysql2require('mysql')为require('mysql2'),API基本兼容。
三、排查网络问题
- 测试连通性:在Node.js服务器上用
ping <MySQL主机>检查是否有丢包,用telnet <MySQL主机> 3306测试端口是否能正常访问,确认没有防火墙或负载均衡器拦截连接。 - 调整TCP保活配置:Linux系统默认的TCP保活时间是7200秒,太长可能导致MySQL断开连接后Node.js无法及时感知。临时调整:
永久生效则编辑echo 300 > /proc/sys/net/ipv4/tcp_keepalive_time/etc/sysctl.conf,添加:
执行net.ipv4.tcp_keepalive_time = 300sysctl -p生效。
四、代码层面最佳实践
- 避免长期持有单个连接:优先使用连接池,它会自动管理连接的复用和销毁,减少连接断开的概率。
- 捕获所有查询错误:每个数据库查询都要处理错误,必要时添加重试逻辑:
function queryWithRetry(sql, params, callback) { pool.query(sql, params, (err, results) => { if (err && err.code === 'ECONNRESET') { // 重试一次 pool.query(sql, params, callback); return; } callback(err, results); }); } // 使用示例 queryWithRetry('INSERT INTO bookings SET ?', { user_id: 1, time: new Date() }, (err, res) => { if (err) { console.error('预订失败:', err); return; } console.log('预订成功'); });
内容的提问来源于stack exchange,提问作者qvasz
相关产品推荐
相关产品推荐

