mysql连接“突然消失”是服务端主动断开空闲连接所致,需用createpool配置合理参数、全局单例、错误重试及兜底处理。

MySQL连接在Node.js中“突然消失”,不是你的代码写错了,而是MySQL服务端主动切断了空闲连接——默认wait_timeout是8小时,但实际很多云数据库(如阿里云RDS、腾讯云CDB)会设为1~4小时,甚至更短。光靠调大服务端参数不可靠,必须在客户端做容错和保活。
用mysql.createPool替代createConnection
单连接(createConnection)无法自动恢复、无法复用、极易泄漏;而连接池(createPool)能自动检测失效连接、按需新建、复用健康连接,是长期运行服务的唯一合理选择。
-
connectionLimit别设太高(如10~20),避免压垮MySQL的max_connections - 务必配
waitForConnections: true和queueLimit: 0,否则高并发时请求会静默失败 -
acquireTimeout或timeout建议设为5000~10000ms,防止卡死在获取连接阶段 - 不用手动
.release()——pool.query()内部已处理;若用pool.getConnection(),则必须调用conn.release()
捕获PROTOCOL_CONNECTION_LOST并重试查询
即使用了连接池,首次执行pool.query()时仍可能拿到一个刚被MySQL断开、但池子还没来得及标记为失效的连接,此时报错PROTOCOL_CONNECTION_LOST。不能只靠重连机制,业务层要兜底。
使用固定的 Next.js/Tailwind/Prisma 技术栈构建并记录独立 SaaS 项目,仅将 FastAPI 用于 Python 工作负载,并遵循严格的架构规范。
- 对关键查询(如登录、支付、事务)加一层简单重试:第一次失败且
err.code === 'PROTOCOL_CONNECTION_LOST',就再执行一次 - 不要无限制重试,最多1~2次,避免雪崩
- 注意:事务场景下不能直接重试整个事务,需结合
SAVEPOINT或幂等设计
定期ping不是必须,但idleTimeoutMillis必须设
老教程里常见的每小时conn.ping()其实多余——连接池本身会在连接空闲超时前自动销毁它;真正该配的是idleTimeoutMillis(默认10000ms),它控制连接在池中最大空闲时间。
- 设为比MySQL的
wait_timeout小至少60秒(例如MySQL是3600秒,这里设3500000) - 这样连接池会在MySQL切断前主动回收并新建连接,比被动
ping更轻量、更可靠 - 如果MySQL侧无法确认
wait_timeout值,保守设为1800000(30分钟)即可
别忽略unhandledRejection导致进程崩溃
用mysql2/promise时,没catch的查询错误(包括连接断开)会触发unhandledRejection,Node.js进程可能直接退出——看起来像“数据库挂了”,其实是JS异常没兜住。
- 所有
await pool.promise().query(...)必须包裹在try/catch里 - 全局监听
process.on('unhandledRejection', ...)仅作兜底告警,不能替代业务层错误处理 - 错误日志里重点看
err.code和err.fatal,区分是网络抖动还是配置错误
最易被忽略的一点:连接池实例必须是全局单例,不能在每个路由或函数里重复createPool——否则连接数会指数级增长,很快触发Too many connections。初始化一次,到处require,才是稳住连接的底层前提。










