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

Node.js使用tedious执行存储过程批量插入的最佳连接管理方法

Node.js 环境下 tedious 驱动批量调用存储过程的连接管理最佳实践

报错根因

你碰到的connect EADDRINUSE 10.78.56.21:1433错误,本质是TCP连接泄漏导致客户端临时端口耗尽,和单连接复用的思路本身无关。问题出在你最初的单连接实现没有做异常兜底:只要循环中任意一次存储过程执行抛错,conn.end()就不会被执行,泄漏的连接占满可用端口后就会触发这个报错。

两种现有实现的问题

  • 原始单连接方案:缺少异常场景下的连接释放逻辑,单次执行失败就会泄漏连接,批量操作、高并发场景下极容易触发端口耗尽、数据库连接数超限问题;另外如果批量数据量很大,单连接长时间空闲也可能被数据库侧的超时策略主动断开。
  • 每次插入新建/销毁连接的方案:性能极差,每次TCP建连、鉴权、TLS协商的开销远高于存储过程本身的执行开销,批量场景下执行效率会比连接复用低几十倍,同时短时间大量创建短连接反而更容易触发EADDRINUSE错误,还可能打满数据库的最大连接数,直接拖垮数据库服务。

推荐实现方案

1. 优先使用连接池

生产环境永远不要手动管理单个数据库连接,直接用连接池是行业通用最佳实践。连接池会自动维护长连接、复用健康连接、回收异常连接、控制总连接数,从根源上避免连接泄漏和端口耗尽问题。
基于tedious生态的标准实现示例:

// 基于tedious封装的数据库驱动,内置生产级连接池能力
const sql = require('mssql')

// 服务启动时全局初始化一次连接池,不要每次操作都新建
const pool = new sql.ConnectionPool({
  server: '10.78.56.21',
  port: 1433,
  database: '你的业务库名',
  user: '数据库账号',
  password: '数据库密码',
  pool: {
    max: 10, // 最大连接数,根据数据库性能配置,一般单实例Node服务设置5-20即可
    min: 2, // 常驻的最小空闲连接数
    idleTimeoutMillis: 30000 // 空闲连接超过30秒自动回收
  }
})
// 初始化连接池
pool.connect()

async function batchInsertClients(parameters) {
  // 开启事务保证批量操作原子性,避免部分插入成功部分失败产生脏数据
  const transaction = new sql.Transaction(pool)
  try {
    await transaction.begin()
    for (const param of parameters) {
      // 每次请求自动从连接池取可用连接,执行完自动归还,不需要手动管理
      await new sql.Request(transaction)
        .execute('PRO_insertValuesClients', param)
    }
    await transaction.commit()
  } catch (err) {
    // 出错直接回滚事务
    await transaction.rollback()
    throw err
  }
  // 注意:不要在这里关闭连接池,连接池要在服务全局常驻,只有进程退出时才调用pool.close()
}

2. 性能优化建议

如果单次批量插入的数据量超过1000条,不要循环单条调用存储过程,建议改用表值参数,把整批数据一次性传给存储过程处理,能减少90%以上的数据库网络交互开销,插入性能会有数量级提升。

3. 轻量场景临时修复方案

如果只是低频率小批量的脚本场景,暂时不想引入连接池,只要给原始单连接代码补上finally块的连接释放逻辑即可解决泄漏问题:

let conn
try {
  conn = await Con.create()
  for (let i = 0; i < parameters.length; i++) {
    await conn.queryExec("PRO_insertValuesClients", parameters[i])
  }
} catch (err) {
  // 自定义错误处理逻辑
  throw err
} finally {
  // 无论执行成功还是失败,都保证连接被关闭
  if (conn) conn.end()
}

注意:这个方案只适合低频脚本场景,线上高并发服务必须使用连接池,否则会出现连接数不足、请求排队的问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 01:03:33