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

Next.js中Prisma批量注册出现重复邮箱P2002报错如何解决?

问题诊断与解决

核心问题分析

你的批量注册报错源于两个关键问题:

  1. 用户生成脚本逻辑失效:生成用户时未正确维护邮箱去重集合,导致users.json中实际存在重复邮箱
  2. 并发请求隐患:极短的请求间隔可能导致数据库还未完成前一个用户写入,就收到下一个相同邮箱的请求

修复步骤

1. 修复用户生成脚本

修改generateUser代码,确保生成的邮箱和用户名完全唯一:

import fs from "fs";
import { faker } from "@faker-js/faker";

const generateUser = () => {
  const users = [];
  // 分别维护用户名和邮箱的去重集合
  const usedUsernames = new Set();
  const usedEmails = new Set();

  for (let i = 0; i < 100; i++) {
    // 生成唯一且长度≥5的用户名
    let username = faker.name.firstName();
    while (usedUsernames.has(username) || username.length < 5) {
      username = faker.name.firstName();
    }

    // 生成唯一邮箱
    let email = faker.internet.email();
    while (usedEmails.has(email)) {
      console.log(`Warning: ${email} 已重复,重新生成邮箱`);
      email = faker.internet.email();
    }

    const password = faker.internet.password();

    const user = { username, email, password };
    users.push(user);

    // 将生成的用户名和邮箱加入去重集合
    usedUsernames.add(username);
    usedEmails.add(email);

    console.log(`已生成用户: ${i+1}`);
  }

  console.log(`共生成 ${users.length} 个唯一用户`);
  const jsonUsers = JSON.stringify(users);

  fs.writeFile("users.json", jsonUsers, (err) => {
    if (err) {
      console.error(err);
      return;
    }
    console.log("用户数据已保存到 users.json");
  });
};

generateUser();

2. 优化批量注册脚本

增加请求间隔,降低数据库并发压力:

import users from "./users.json" assert { type: "json" };
import axios from "axios";

export const registerUsers = async (users) => {
  const failedEmails = [];

  for (let i = 0; i < users.length; i++) {
    const user = users[i];
    const data = {
      username: user.username,
      email: user.email.trim(),
      password: user.password,
    };

    try {
      const response = await axios.post(
        "http://localhost:3000/api/auth/register",
        data
      );
      console.log(`用户 ${i+1} 注册成功:`, response.data.email);
    } catch (error) {
      console.error(
        `用户 ${i+1} (${user.email}) 注册失败`,
        error.response?.data || error.message
      );
      if (error.response?.data?.errors?.includes("This e-mail is already taken.")) {
        failedEmails.push(user.email);
      }
    }

    // 增加间隔到50ms,避免并发冲突
    await new Promise((resolve) => setTimeout(resolve, 50));
  }

  console.log("批量注册完成!");
  console.log(`注册失败的邮箱 (${failedEmails.length} 个): ${failedEmails.join(", ")}`);
};

registerUsers(users);

3. 增强API鲁棒性(可选)

在Prisma执行创建操作前,主动查询邮箱是否已存在:

// 在原API的try块前添加
const existingUser = await prisma.user.findUnique({
  where: { email },
});

if (existingUser) {
  return res.status(400).json({
    success: false,
    errors: ["This e-mail is already taken."],
  });
}

// 继续执行原create逻辑
const user = await prisma.user.create({...});

验证方法

  1. 运行修复后的生成脚本,打开users.json确认无重复邮箱
  2. 清空数据库用户数据后,再运行批量注册脚本即可解决问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 00:43:20