如何在 Node.js 中正确管理 MySQL 连接(避免连接泄漏与性能问题)

7次阅读

如何在 Node.js 中正确管理 MySQL 连接(避免连接泄漏与性能问题)

本文详解 node.js 中使用 `mysql` 包时的连接生命周期管理:说明单连接长期复用的合理性、为何不应在每次请求后手动 `end()`,以及如何通过连接池实现高性能、安全的数据库访问。

在你当前的代码中,使用 mysql.createConnection() 创建一个全局连接并在多个路由中复用,本身并非错误实践——只要该连接保持活跃且未被意外中断,它完全可以支撑整个应用生命周期内的请求。但关键在于:你不应在每个 http 请求处理完后调用 connection.end()。原因如下:

  • connection.end() 是终结整个连接对象的操作,执行后该连接不可再用;
  • 若在 /getAll 路由中调用 .end(),后续请求再调用 connection.query() 就会抛出 Cannot enqueue Query after invoking quit. 等错误;
  • 单连接长期持有虽可行,但存在单点故障风险(如网络闪断、MySQL 服务重启),且无法横向扩展。

推荐方案:改用连接池(Connection Pool)
连接池自动维护一组可复用的连接,在需要时分配、使用后归还,既避免频繁建立/销毁开销,又具备容错与并发能力。以下是标准实践:

const mysql = require('mysql');  // 创建连接池(推荐配置) const pool = mysql.createPool({   connectionLimit: 10,      // 最大并发连接数   host: 'localhost',   user: 'your_user',   password: 'your_password',   database: 'your_db',   waitForConnections: true, // 队列等待(默认 true)   queueLimit: 0,            // 无限制排队(0 表示不限)   timeout: 60000,           // 获取连接超时时间(ms) });  // 在路由中安全使用 router.get('/getAll', (req, res) => {   pool.query('SELECT * FROM admin', (error, results) => {     if (error) {       console.error('Database query failed:', error);       return res.status(500).json({ status: 500, error: 'Database error' });     }     res.status(200).json({ status: 200, data: results });   }); });

? 重要注意事项:

  • ✅ 连接池无需、也不应手动关闭每个连接 —— pool.query() 内部自动完成获取 → 执行 → 归还流程;

  • ✅ 应在应用优雅退出时关闭整个池,防止进程残留:

    // 应用关闭前清理 const gracefulShutdown = () => {   pool.end((err) => {     if (err) {       console.error('Error closing MySQL pool:', err);       process.exit(1);     }     console.log('MySQL connection pool closed.');     process.exit(0);   }); };  process.on('SIGTERM', gracefulShutdown); process.on('SIGINT',  gracefulShutdown);
  • ⚠️ 避免混合使用单连接 + 连接池;也不要在请求中 createConnection() 后不 end()(会导致连接泄漏);

  • ? 生产环境建议配合 mysql2 包(支持 promise、更好的错误处理和性能)及连接健康检查(如定期 PING)。

总结:单连接适合极简原型,但真实项目务必迁移到连接池。它不仅是最佳实践,更是保障稳定性、可伸缩性与资源可控性的基石。

text=ZqhQzanResources