You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Typeorm+NestJS原生查询触发ER_CON_COUNT_ERROR:连接数过多问题求助

解决TypeORM每次查询创建新连接导致连接数过多的问题

问题根源

你的DBDataSource类每次调用_mysql方法时都会新建一个DataSource实例,每个实例都会创建独立的数据库连接池。随着请求量增加,连接数会迅速超过MySQL的最大连接限制,触发ER_CON_COUNT_ERROR错误。

解决方案:单例连接池复用

重构代码,确保整个应用只初始化一个DataSource实例,共用同一个连接池。

1. 重构DBDataSource类(单例连接)

修改data-source.ts,将DataSource作为类的成员变量,仅初始化一次:

import { DataSource } from "typeorm";

export class DBDataSource {
  private readonly dataSource: DataSource;

  constructor() {
    // 初始化唯一的DataSource实例
    this.dataSource = new DataSource({
      type: "mysql",
      host: process.env.DATABASE_HOST,
      port: 3306,
      username: process.env.DATABASE_USER,
      password: process.env.DATABASE_PASS,
      database: process.env.DATABASE_NAME,
      synchronize: false,
      // 配置连接池参数,限制最大连接数(根据MySQL配置调整)
      poolSize: 10,
    });
    // 预初始化连接(或在第一次查询时懒加载)
    this.initConnection();
  }

  private async initConnection() {
    if (!this.dataSource.isInitialized) {
      try {
        await this.dataSource.initialize();
        console.log("数据库连接初始化成功");
      } catch (error) {
        console.error("数据库连接初始化失败:", error?.message);
      }
    }
  }

  async mysql(query: string, parameters?: any[]) {
    // 确保连接已初始化
    await this.initConnection();
    // 使用参数化查询避免SQL注入风险
    return this.dataSource.query(query, parameters);
  }
}

2. 在NestJS中注册单例服务

在你的根模块(如app.module.ts)中,将DBDataSource注册为单例,确保整个应用共享同一个实例:

import { Module } from '@nestjs/common';
import { DBDataSource } from './Config/data-source';
import { BookService } from './book.services';
import { HttpModule } from '@nestjs/axios';

@Module({
  imports: [HttpModule], // 导入HttpModule以提供HttpService
  providers: [
    BookService,
    {
      provide: DBDataSource,
      useValue: new DBDataSource(), // 单例实例
    },
  ],
})
export class AppModule {}

3. 修改查询代码,避免SQL注入

更新book.services.ts,使用参数化查询替代字符串拼接:

import { Injectable} from '@nestjs/common';
import { DBDataSource } from '../Config/data-source';
import { HttpService } from '@nestjs/axios';

@Injectable()
export class BookService {
  constructor(
    private httpService: HttpService,
    private readonly dbDataSource: DBDataSource
  )  {}

  async GET_BookByID(id: string){
    // 参数化查询:用?占位符,参数放在数组中
    const resbook = await this.dbDataSource.mysql(
      'SELECT * FROM mst_book WHERE id = ?',
      [id]
    );
    return resbook; 
  }
}

关键说明

  • 连接池复用:现在整个应用只有一个DataSource实例,TypeORM会自动管理连接池,复用空闲连接,避免重复创建连接。
  • 连接数控制:通过poolSize配置连接池最大连接数,不要超过MySQL的max_connections设置(默认151)。
  • 安全修复:参数化查询彻底避免了SQL注入风险,这是字符串拼接查询的严重安全漏洞。

内容的提问来源于stack exchange,提问作者riski

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 09:55:31