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

NodeJS + Prisma执行长任务频繁断连?(ConnectorError)

解决Prisma+PlanetScale大插入超时及后台任务执行问题

一、让服务器后台执行任务,无需前端等待

直接在Express接口中先返回响应,再异步执行任务,避免前端因长时间等待导致连接断开:

app.post('/', async (req, res) => {
  // 立即返回202状态码,告知任务已接收
  res.status(202).json({ message: '任务已启动,将在后台执行' });

  // 后台异步执行插入逻辑,不阻塞响应返回
  (async () => {
    try {
      const { items } = req.body;
      // 转换数据格式
      let prismaItems = await Promise.all(items.map(async (item) => {
        let bla = await Promise.all(item.bla.map(async innerItem => {
          // ...你的内部数据转换逻辑
        }));
        return { /* 构造sentence对应的数据结构 */ };
      }));

      // 执行插入(后续需优化长事务问题)
      await prisma.megaItem.create({
        data: {
          title: "My title",
          sentences: { create: [...prismaItems] }
        }
      });
      console.log('插入任务完成');
    } catch (err) {
      console.error('插入任务失败:', err);
    }
  })();
});

如果需要更可靠的任务管理(支持失败重试、状态监控),推荐使用任务队列(如BullMQ):

  • 前端请求时将任务加入队列,立即返回响应
  • 单独启动Worker进程后台处理队列任务

示例代码:

// 队列定义(queue.js)
const { Queue } = require('bullmq');
const insertQueue = new Queue('megaInsert');

// 接口处理逻辑
app.post('/', async (req, res) => {
  await insertQueue.add('batchInsert', { items: req.body.items });
  res.status(202).json({ message: '任务已加入队列,后台处理中' });
});

// Worker进程(worker.js)
const { Worker } = require('bullmq');
const prisma = require('./prisma');

const worker = new Worker('megaInsert', async (job) => {
  const { items } = job.data;
  // 数据转换逻辑
  let prismaItems = await Promise.all(items.map(async (item) => {
    // ...转换代码
  }));

  // 执行分批插入(见下文优化方案)
  const megaItem = await prisma.megaItem.create({ data: { title: "My title" } });
  const batchSize = 50;
  for (let i = 0; i < prismaItems.length; i += batchSize) {
    const batch = prismaItems.slice(i, i + batchSize);
    await prisma.sentence.createMany({
      data: batch.map(s => ({ megaItemId: megaItem.id, ...s }))
    });
  }
});

worker.on('completed', (job) => console.log(`任务 ${job.id} 完成`));
worker.on('failed', (job, err) => console.error(`任务 ${job.id} 失败: ${err}`));

二、解决PlanetScale事务超时问题

你的报错是PlanetScale的tx killer机制触发的——它会自动终止运行超过10秒的事务。当前嵌套create的方式会把所有插入操作放在一个事务中,数据量大时必然超时,优化方案如下:

1. 拆分事务,分批插入

先创建megaItem主记录,再用createMany分批插入关联的sentences子记录,每个批次的事务时间短,不会触发超时:

// 先创建主记录
const megaItem = await prisma.megaItem.create({
  data: { title: "My title" }
});

// 分批次插入子记录
const batchSize = 50; // 根据数据大小调整,建议50-100条/批
const total = prismaItems.length;

for (let i = 0; i < total; i += batchSize) {
  const batch = prismaItems.slice(i, i + batchSize);
  await prisma.sentence.createMany({
    data: batch.map(sentence => ({
      megaItemId: megaItem.id,
      // 填充sentence的其他字段
      ...sentence
    }))
  });
}

2. 禁用Prisma自动事务(不推荐)

如果必须使用嵌套创建,可尝试禁用Prisma的自动事务管理,但会失去数据一致性保障:

await prisma.megaItem.create({
  data: { /* ... */ },
  transaction: { enabled: false }
});

关键注意事项

  • 独立NodeJS服务器需用PM2等进程管理工具托管,避免进程意外退出中断任务
  • 批量插入的batchSize需根据单条数据大小测试调整,找到最优值
  • 任务队列方案更适合长时间运行的任务,支持重试、监控和持久化

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 18:30:49