Next.js中Prisma批量注册出现重复邮箱P2002报错如何解决?
问题诊断与解决
核心问题分析
你的批量注册报错源于两个关键问题:
- 用户生成脚本逻辑失效:生成用户时未正确维护邮箱去重集合,导致
users.json中实际存在重复邮箱 - 并发请求隐患:极短的请求间隔可能导致数据库还未完成前一个用户写入,就收到下一个相同邮箱的请求
修复步骤
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({...});
验证方法
- 运行修复后的生成脚本,打开
users.json确认无重复邮箱 - 清空数据库用户数据后,再运行批量注册脚本即可解决问题
内容的提问来源于stack exchange,提问作者periakteon
相关产品推荐
相关产品推荐

