TypeORM 0.3.0+版本DataSource连接池突然关闭问题咨询
TypeORM 0.3.x 并发请求报「Pool is closed」问题解决方案
问题复现场景
- 项目封装了独立的数据库控制器类,在TypeORM 0.3.7版本中通过如下逻辑初始化DataSource:
const dataSource: DataSource = new DataSource({ type: "mariadb", host: process.env.DB_HOST, username: process.env.DB_USER, password: process.env.DB_PASS, database: database, logging: false, name: UUID.v4(), synchronize: false, entities: [path.join(__dirname, "../", "Models", "*.js")] }); const createdConnection: DataSource = await dataSource.initialize(); return Promise.resolve(new ReturnStatus(true, "Connection created", createdConnection));
- 业务层通过如下方式并发拉取数据:
Promise.all([GetSites(), GetDetails(), GetCategories()]);
- 服务端处理逻辑:每个请求方法都会独立调用上述控制器逻辑,创建全新的DataSource实例,运行时抛出如下错误:
Error: Pool is closed. at Handshake.onConnect (C:\Users\<USER>\Project\node_modules\mysql\lib\Pool.js:52:15) at Handshake.<anonymous> (C:\Users\<USER>\ProjectAPI\node_modules\mysql\lib\Connection.js:526:10)
- 版本关联:相同代码在升级到TypeORM 0.3.7前可正常运行,实测该问题从TypeORM 0.3.0版本变更后开始出现。
核心原因
TypeORM 0.3.x版本重构了整套连接管理逻辑:
- 0.2.x版本存在全局连接管理器,所有通过
name标识的连接都会被全局持有引用,不会被垃圾回收,即使每次请求生成随机UUID的新连接,也会被全局缓存,不会触发连接池销毁。 - 0.3.x版本移除了全局连接管理器,不再自动持有DataSource实例的引用。当前在请求方法内创建局部DataSource实例,方法执行完后实例失去引用,会被V8垃圾回收,回收时会自动销毁关联的数据库连接池。并发场景下,其他正在执行的请求如果拿到了正在被销毁的连接池引用,就会抛出
Pool is closed错误。
正确使用方式
不需要执行额外初始化操作,也不需要回退到已废弃的Connection API,按照官方推荐的单例模式使用即可:
- 废弃「请求级别创建DataSource实例」的逻辑,在应用启动阶段全局初始化一次DataSource,后续所有数据库操作都复用这同一个实例。
- 不需要调用已标记为废弃的
datasource.connect()方法,initialize()方法已经完成了连接池初始化、实体注册的全部流程,初始化完成即可直接使用。 - DataSource内部自带连接池管理,并发请求下会自动分配、回收连接,不需要为每个请求单独创建连接。
全局初始化示例:
// 全局导出唯一的DataSource实例,整个应用生命周期复用 export const AppDataSource = new DataSource({ type: "mariadb", host: process.env.DB_HOST, username: process.env.DB_USER, password: process.env.DB_PASS, database: database, logging: false, // 全局单例不需要生成随机name,可直接删除该配置 synchronize: false, entities: [path.join(__dirname, "../", "Models", "*.js")], // 可根据业务并发量配置连接池参数 pool: { max: 10, min: 2 } }); // 应用启动入口处执行一次初始化即可 await AppDataSource.initialize();
后续业务代码中,直接导入AppDataSource获取Repository、执行查询即可,并发场景下也不会出现连接池关闭的问题。
补充:如果有多数据源动态切换的需求,也需要为每个数据库维护长生命周期的DataSource实例,禁止在请求级别频繁创建、销毁DataSource实例,否则不仅会触发连接池错误,还会带来反复新建连接的性能损耗。
内容的提问来源于stack exchange,提问作者user17145524
相关产品推荐
相关产品推荐

