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

使用Promise.all并发执行超12个Prisma事务时报错排查

Prisma事务并发调用超时:中间件误用主客户端导致的问题

问题场景

我有一个使用Prisma $transaction的API函数,用Vitest做并发调用测试时,当并发数超过12次就会触发超时错误,12次以内则正常。

函数代码

const verifyEmail = (data) => {
    return prisma.$transaction(async tx => {
       // 读取和更新操作
    })
}

测试代码

test("run verifyEmail multiple times", async () => {
    await Promise.all(myCredentials.map(data => verifyEmail(data)))
})

报错信息

Transaction API error: Unable to start a transaction in the given time.

调整超时时间和maxWait参数无法解决问题,排查后怀疑是Prisma中间件内的查询误用了主Prisma客户端而非事务上下文的客户端。

问题原因

Prisma的事务依赖专属的连接上下文(即$transaction回调中的tx实例),如果中间件里直接使用全局的prisma客户端执行查询,会绕过事务上下文,创建新的独立数据库连接。当并发请求数超过数据库连接池的默认上限(通常10-15)时,连接池耗尽,新的事务无法获取连接,最终触发超时错误。

解决方案

修改Prisma中间件,确保所有数据库操作都使用当前上下文的客户端(事务场景下自动复用tx实例),而非全局的prisma客户端:

错误的中间件示例

// 错误:直接使用全局prisma客户端,事务中会创建新连接
prisma.$use(async (params, next) => {
  await prisma.log.create({ data: { action: params.action } })
  return next(params)
})

修正后的中间件示例

// 正确:使用当前上下文的客户端,事务内自动使用tx实例
prisma.$use(async (params, next) => {
  // params.prisma 会指向当前操作的客户端(事务场景下是tx)
  const client = params.prisma || prisma
  await client.log.create({ data: { action: params.action } })
  return next(params)
})

额外注意事项

  1. 检查所有中间件中的数据库操作,确保统一使用params.prisma获取客户端实例,避免硬编码全局prisma。
  2. 若需要更高并发,可以适当调整数据库连接池配置(如PostgreSQL的max_connections、Prisma的connection_limit),但优先解决中间件的客户端误用问题,这才是根本原因。

内容的提问来源于stack exchange,提问作者Arash Jahan Bakhshan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 10:12:40