Node.js 数据库连接池管理与优化实践
深入讲解 Node.js 数据库连接池的配置管理与性能优化,涵盖连接池工作原理、参数调优、SQL 注入防护、事务处理、连接泄漏排查、假死保活等内容,附 mysql2 与 pg 驱动代码示例,提升数据库访问的稳定性与吞吐量。
# Node.js 数据库连接池管理与优化实践
> 数据库连接频繁建立断开,性能急剧下降;连接不释放,直接打爆数据库。连接池是解决之道,但配置不当反而更糟。本文讲透连接池管理。
## 一、为什么要连接池
- 建立数据库连接开销大(TCP + 认证)
- 并发高时反复建连会拖垮数据库
- 连接池复用连接,显著提升吞吐
## 二、mysql2 连接池基本用法
```js
const mysql = require("mysql2/promise");
// 创建连接池
const pool = mysql.createPool({
host: "localhost",
user: "root",
password: "password",
database: "app_db",
waitForConnections: true, // 无可用连接时排队等待
connectionLimit: 10, // 最大连接数
queueLimit: 0 // 队列不限制
});
// 使用
const [rows] = await pool.query("SELECT * FROM users WHERE id = ?", [id]);
```
> 使用占位符 ? 传参,杜绝 SQL 注入。
## 三、参数调优建议
- **connectionLimit**:默认 10,根据并发调大,一般 20-50
- **waitForConnections**:必须 true,否则高峰期直接报错
- **queueLimit**:0 表示无限排队,防止请求失败
- **connectTimeout**:建议 10 秒,避免长时间等待
- **maxIdle**(部分驱动):空闲连接上限
```js
// 更完整的配置
const pool = mysql.createPool({
host: "localhost",
user: "root",
password: "password",
database: "app_db",
connectionLimit: 30,
waitForConnections: true,
queueLimit: 100,
connectTimeout: 10000,
charset: "utf8mb4"
});
```
## 四、事务处理
```js
// 事务必须在同一个连接上执行
const conn = await pool.getConnection();
try {
await conn.beginTransaction();
await conn.query("UPDATE accounts SET balance = balance - 100 WHERE id = 1");
await conn.query("UPDATE accounts SET balance = balance + 100 WHERE id = 2");
await conn.commit();
} catch (err) {
await conn.rollback();
throw err;
} finally {
conn.release(); // 释放连接回池
}
```
> 事务用完必须 release,否则连接泄漏,池被耗尽。
## 五、PostgreSQL(pg 驱动)
```js
const { Pool } = require("pg");
const pool = new Pool({
host: "localhost",
database: "app_db",
user: "app_user",
max: 20, // 最大连接数
idleTimeoutMillis: 30000,
connectionTimeoutMillis: 5000
});
const { rows } = await pool.query("SELECT * FROM users WHERE id = $1", [id]);
```
## 六、常见问题排查
> ⚠️ **坑1:连接耗尽 ER_CON_COUNT_ERROR**
原因:连接未释放或连接数过小。
```js
// 排查:进程连接数
SHOW STATUS LIKE "Threads_connected";
// 数据库侧查看
SHOW PROCESSLIST;
```
> ⚠️ **坑2:连接泄漏**
获取连接后忘记 release,或被异常中断。确保 try/finally 释放。
> ⚠️ **坑3:连接假死**
数据库重启后旧连接失效,建议设置自动重连或定期 ping。
```js
// 定期保活(每 60 秒)
setInterval(async () => {
try { await pool.query("SELECT 1"); }
catch (e) { console.error("连接异常:", e.message); }
}, 60000);
```
## 七、监控指标
- 活跃连接数、等待队列长度
- 连接获取耗时
- 慢查询数量
## 八、小结
连接池管理核心三点:
1. 参数合理(连接数、超时、队列)
2. 事务必须释放连接
3. 定期保活防假死
做好这三点,数据库层稳定可靠。