Node.js + mysql2/promise出现Too many connections错误的解决咨询
问题根因
你遇到「Too many connections」报错,本质是现有连接封装完全没有发挥连接池的复用价值,反而制造了大量冗余连接:
当前实现里,每次业务接口调用connect()函数时,都会重新执行createPool()生成一个全新的独立连接池实例。哪怕你给单个池配了10的连接上限,高并发场景下短时间内就能创建出几十个甚至上百个独立池,每个池都会单独向MySQL申请连接,很快就会打满MySQL的最大连接数上限。
另外现有业务代码里的conn.end()也存在释放漏洞:只要查询报错、接口抛异常,conn.end()就不会被执行,新建的连接池会一直持有已申请的MySQL连接不释放,进一步加剧连接占用。
方案选型说明
你提到的两个改造方向都不是最优解:
- 不建议把
createPool替换成createConnection做单连接:单连接无法支撑并发请求,遇到慢查询会导致所有后续请求排队阻塞,性能比连接池差很多 - 也不需要额外写逻辑硬控“单个数据库连接实例”:连接池的设计初衷就是全局单例复用,只要调整现有封装的初始化时机,就能彻底解决连接超限的问题
正确改造方式
- 把连接池从「按需调用新建」改成「应用启动时全局初始化一次,全链路复用同一个池实例」,直接替换原有的connect封装:
import { createPool, Pool } from 'mysql2/promise'; // 全局只创建一次池,所有接口共用 export const pool: Pool = createPool({ host: 'localhost', port: 3306, user: 'root', password: '', database: 'mendozarq', connectionLimit: 10 });
- 改造业务控制器代码,删掉手动创建连接、手动
end()池的逻辑,直接引入全局池执行查询即可:
import { Response, Request } from 'express'; import { FieldPacket } from 'mysql2/promise'; import { pool } from './../../classes/database'; import { Personal } from './../../models/personal.interface'; export const getAllPersonal = async (req: Request, res: Response) => { try { // 连接池会自动管理连接的获取、复用、超时回收 const [personal]: [Personal[], FieldPacket[]] = await pool.query('SELECT * FROM personal ORDER BY creadoEn DESC'); return res.status(200).json(personal); } catch (error) { return res.status(400).json({ error }); } }
补充注意事项
- 连接池实例本身是全局单例,绝对不能在单次请求结束后手动调用
pool.end(),否则会直接销毁整个池,后续请求会因为池已关闭报错 - 改造完成后如果还是偶发连接超限,可以排查下是不是存在未提交/回滚的长事务,导致池内连接被长期占用无法归还
- 可以根据实际并发量动态调整
connectionLimit参数,不需要硬卡10的上限
内容的提问来源于stack exchange,提问作者Bladimir Medrano Vargas
相关产品推荐
相关产品推荐

