Node.js 连接MySQL出现read ECONNRESET错误如何解决
解决方案
你当前使用单个长连接直连MySQL,未处理连接异常、也没有自动重连机制,当网络链路中间节点(防火墙、负载均衡、数据库本身)主动断开空闲超时的连接时,就会抛出未捕获的ECONNRESET异常导致服务崩溃。你之前的定时探活方案未覆盖连接中断的异常处理逻辑,所以无法生效。
方案1:使用连接池(最推荐)
连接池会自动管理连接的生命周期,自动销毁超时空闲连接、新建可用连接,同时支持连接复用,性能更稳定。
代码示例:
const mysql = require('mysql'); // 创建连接池 const pool = mysql.createPool({ host: process.env.DATABASE_HOST, user: process.env.DATABASE_USER, password: process.env.DATABASE_PASSWORD, database: process.env.DATABASE, connectionLimit: 10, // 按需调整最大连接数 acquireTimeout: 30000, idleTimeout: 600000, // 空闲连接超时时间,设置为比数据库/防火墙的超时时间短 }); // 使用连接池执行查询示例 pool.query('SELECT 1 + 1 AS solution', function (error, results, fields) { if (error) throw error; console.log('The solution is: ', results[0].solution); });
说明:连接池不需要手动调用connect,内部会自动维护连接状态,出现异常会自动销毁坏连接并新建。
方案2:单连接增加错误监听和自动重连逻辑
如果必须使用单连接,需要监听error事件,连接断开时自动触发重连:
const mysql = require('mysql'); let con; function handleDisconnect() { con = mysql.createConnection({ host: process.env.DATABASE_HOST, user: process.env.DATABASE_USER, password: process.env.DATABASE_PASSWORD, database: process.env.DATABASE }); con.connect(function(err) { if (err) { console.log('连接失败,2秒后重试:', err); setTimeout(handleDisconnect, 2000); } else { console.log("Connected to Database!"); } }); // 监听连接错误事件 con.on('error', function(err) { console.log('数据库连接异常:', err); if(err.code === 'PROTOCOL_CONNECTION_LOST' || err.code === 'ECONNRESET') { // 连接断开时自动重连 handleDisconnect(); } else { throw err; } }); } // 初始化连接 handleDisconnect();
说明:该方案会在连接被断开后自动重建连接,避免服务直接崩溃。配合你原来的定时探活逻辑时,注意探活代码也要捕获异常,避免异常抛出。
可选优化配置
- 如果有权限调整MySQL配置,可将
wait_timeout和interactive_timeout调整为更长的时间,减少连接被主动断开的频率 - 定时探活的间隔建议设置为比链路中最短的超时时间(比如防火墙超时、负载均衡超时、数据库超时)短2-3分钟,确保探活请求能在连接被断开前发送。
内容的提问来源于stack exchange,提问作者Maggimann
相关产品推荐
相关产品推荐

