3.8 KiB
3.8 KiB
部署修复说明
问题解决
已修复在推送到现有环境时遇到的外键约束错误:
Error: insert or update on table "users" violates foreign key constraint "users_subscriptionPlanId_fkey"
解决方案
通过修改种子脚本 (prisma/seed.ts
),确保在数据库推送时:
- 创建必需的套餐:使用
upsert
确保 'free' 和 'pro' 套餐存在 - 修复用户数据:自动修复无效的套餐引用
- 验证数据完整性:确保所有用户都有有效的套餐关联
使用方法
现在可以直接使用现有命令进行部署:
npm run db:push
这个命令会:
- 推送数据库架构 (
prisma db push
) - 运行种子脚本 (
npm run db:seed
) - 自动处理数据修复
种子脚本改进
主要变更
-
使用 upsert 而不是 create
// 之前:如果套餐存在就跳过 if (existingPlans > 0) return // 现在:确保必需套餐存在 await prisma.subscriptionPlan.upsert({ where: { id: 'free' }, update: { name: 'free', isActive: true }, create: { /* 完整套餐数据 */ } })
-
智能用户数据修复
// 检查所有用户的套餐引用 const validPlanIds = ['free', 'pro'] const usersToUpdate = users.filter(user => { const hasValidSubscribePlan = validPlanIds.includes(user.subscribePlan) const hasValidSubscriptionPlanId = validPlanIds.includes(user.subscriptionPlanId) return !hasValidSubscribePlan || !hasValidSubscriptionPlanId }) // 修复无效引用 for (const user of usersToUpdate) { await prisma.user.update({ where: { id: user.id }, data: { subscribePlan: validPlanIds.includes(user.subscribePlan) ? user.subscribePlan : 'free', subscriptionPlanId: validPlanIds.includes(user.subscribePlan) ? user.subscribePlan : 'free' } }) }
执行流程
- 创建/更新套餐:确保 'free' 和 'pro' 套餐存在
- 检查用户数据:找出有无效套餐引用的用户
- 修复用户数据:将无效引用改为 'free'
- 验证结果:确认所有数据都是一致的
测试验证
种子脚本运行结果:
🌱 Starting database seeding...
📦 Ensuring essential subscription plans exist...
✅ Created subscription plan: Free Plan
✅ Created subscription plan: Pro Plan
👥 Updating existing users...
👥 No users need subscription plan updates
📊 Seeding completed:
• 2 subscription plans created
• 2 users have valid plan associations
🎉 Database seeding finished successfully!
部署到现有环境
现在可以安全地部署到任何现有环境:
-
本地测试:
npm run db:push npm run build
-
生产部署:
npm run db:push npm start
优势
- 无需额外脚本:使用现有的
npm run db:push
命令 - 自动修复:种子脚本自动处理数据不一致问题
- 向后兼容:不会破坏现有数据
- 幂等操作:可以重复运行而不会出错
注意事项
-
Stripe 配置:部署后需要设置 Pro 套餐的 Stripe 价格 ID
UPDATE subscription_plans SET "stripePriceId" = 'price_your_stripe_price_id' WHERE name = 'pro';
-
数据验证:部署后验证定价页面和订阅功能
-
备份建议:在生产环境部署前建议备份数据库
故障排除
如果仍然遇到问题:
-
检查套餐:
SELECT id, name, "isActive" FROM subscription_plans;
-
检查用户:
SELECT "subscribePlan", COUNT(*) FROM users GROUP BY "subscribePlan";
-
手动修复:
UPDATE users SET "subscribePlan" = 'free' WHERE "subscribePlan" NOT IN ('free', 'pro');