【Node.js】为什么数据库连接总是中断?

Node.js 中使用 import mysql from 'mysql2/promise'; 本身并不会 直接导致数据库停止工作。但在长时间运行的 Node.js 程序中,如果代码编写不当(特别是连接管理方面),确实会导致数据库连接耗尽、超时或导致 Node.js 应用崩溃。

以下是几个可能导致"数据库停止工作"或"连接失效"的关键原因及解决方法:

1. 连接泄露(最常见原因)

如果你每次执行查询都创建一个新的连接(createConnection)而没有手动关闭它(.end()),或者在高并发下没有正确释放连接,数据库很快就会达到 max_connections(最大连接数)限制。

  • 后果: 数据库拒绝新的连接,报错 Too many connections
  • 解决方法: 使用 连接池 (Connection Pool)

2. 空闲超时 (Idle Timeout)

MySQL 服务器有一个参数叫 wait_timeout(通常默认为 8 小时)。如果一个连接长时间没有任何操作,MySQL 服务器会强制断开这个连接。

  • 后果: 当你的程序在长时间休眠后再次使用该连接时,会报错 Can't add new command when connection is in closed stateread ECONNRESET
  • 解决方法: 连接池会自动处理这个问题,它会检查连接的有效性并在需要时重新创建连接。

3. 未捕获的 Promise 异常

使用 mysql2/promise 时,如果数据库查询报错(如 SQL 语法错误、连接断开)而你没有使用 try...catch 捕获异常,Node.js 进程可能会触发 unhandledRejection 甚至崩溃。

  • 后果: Node.js 应用停止运行,看起来像是数据库"坏了"。
  • 解决方法: 始终使用 try...catch 包裹异步操作。

最佳实践:如何正确长期运行

为了保证 Node.js 长时间运行且数据库稳定,你应该按照以下方式编写代码:

推荐:使用连接池 (Connection Pool)

连接池会自动管理连接的创建、复用和销毁,是长生命周期应用(如 Web 服务器)的标准做法。

javascript 复制代码
import mysql from 'mysql2/promise';

// 1. 创建连接池(只需创建一次,全局复用)
const pool = mysql.createPool({
  host: 'localhost',
  user: 'root',
  password: 'password',
  database: 'test',
  waitForConnections: true,
  connectionLimit: 10, // 最大连接数
  queueLimit: 0,
  enableKeepAlive: true, // 保持心跳,防止被服务器断开
  keepAliveInitialDelay: 10000
});

async function queryData() {
  try {
    // 2. 直接从池中执行(内部会自动获取、执行、释放连接)
    const [rows] = await pool.query('SELECT * FROM users WHERE id = ?', [1]);
    return rows;
  } catch (error) {
    console.error('数据库查询出错:', error);
  }
}

// 周期性运行,不会导致数据库停止
setInterval(async () => {
  const data = await queryData();
  console.log('查询结果:', data);
}, 60000); 

检查清单(防止失效):

  1. 使用 Pool 而不是 Connection: 永远不要在循环或频繁触发的函数中调用 mysql.createConnection()
  2. 启用 KeepAlive:createPool 配置中加入 enableKeepAlive: true。这会让驱动程序定期发送微小的包,防止防火墙或 MySQL 服务器因为该连接"太安静"而将其切断。
  3. 异常处理: 确保所有的 await 都在 try...catch 中,防止程序因为单个查询失败而挂掉。
  4. 不要手动关闭池: 除非你的程序要完全关闭,否则不要调用 pool.end()

总结

单纯的 import 没问题,但要确保使用 createPool 而不是 createConnection。只要使用了连接池并妥善处理了 try...catch,你的 Node.js 程序跑一年数据库也不会因为连接问题停止工作。

相关推荐
IvorySQL9 小时前
PostgreSQL 日报 | JOIN 与外键优化(8 月 9 日)
数据库·postgresql
ltl10 小时前
自治数据库十年回顾:Peloton、NoisePage、OtterTune 到云原生 auto-tuning
数据库
灯澜忆梦11 小时前
【MySQL10】进阶篇 | 索引_#2性能优化
数据库·sql·mysql·性能优化
C++ 老炮儿的技术栈13 小时前
从 Qt Designer 属性编辑器的层级可以看到继承链
c语言·数据库·c++·qt·sqlite·visual studio
MC皮蛋侠客13 小时前
Redis 系列(一):全景与最小闭环——从 `SET` 命令到内存数据结构
数据结构·数据库·redis
zt1985q15 小时前
本地部署开源网络书签与内容管理工具 Karakeep 并实现外部访问
运维·服务器·网络·数据库·网络协议·开源
IvorySQL16 小时前
PostgreSQL 日报| PostgreSQL 19 默认 WAL 压缩算法(8 月 8 日)
数据库·postgresql·区块链
油丶酸萝卜别吃16 小时前
MySQL B+ 树查询全过程详解
数据库·mysql
leisoo809716 小时前
股票数据本地化存储实战:JSON、数据库与列式存储的方案对比
jvm·数据库·json
Exclusive_Cat16 小时前
MySQL回表机制解析与优化策略
数据库·sql