Vibe Tutorial
数据持久化与数据库

7.12 实战避坑案例

Tip

很多时候,阻挡你前进的不是深奥的算法,而是一个漏掉的指令,或者密码里一个不起眼的特殊字符。


1. 核心避坑:四大"鬼故事"

鬼故事一:消失的字段 (Schema 不一致)

  • 现象:你在数据库里明明加了 vip 字段,但在代码里写 user.vip 时,VS Code 死活报错说"不存在"。
  • 真相:这就像是你给房子加盖了一层楼 (DB 变了),但你手里的施工图纸 (Client) 还是旧的。Prisma 不会自动更新它的类型定义。
  • 解法:养成肌肉记忆,依然是那句咒语:
    npx prisma generate
    

鬼故事二:连接数爆炸 (Serverless 的坑)

  • 现象:本地开发一切正常。一上线,只要稍微有几个人同时访问,就报错 Current role has too many connections
  • 真相:Serverless 函数就像临时工。来一个请求,它就雇一个临时工,占一条电话线 (数据库连接)。请求一多,电话线就不够用了。
  • 解法:使用 Supabase 的连接池 (PgBouncer)
    • 它像一个总机接线员,帮大家复用电话线。
    • 配置:用那个端口是 6543 的 URL,而不是 5432 的。

鬼故事三:密码里的"陷阱" (URL 编码)

  • 现象:为了安全,你把数据库密码设成了 Lov3#C0de?。结果启动报错 Invalid URL
  • 真相:在 URL 规则里,# 是锚点,? 是查询参数。程序以为你的密码在 # 那里就结束了。
  • 解法
    1. 用 URL Encode 工具转义 (把 # 变成 %23)。
    2. 或者简单点:改个纯字母数字的密码

鬼故事四:无限重生的客户端 (Next.js 热重载)

  • 现象:开发时好好的,你保存了几次代码,终端突然报错 Too many clients already existed
  • 真相:Next.js 在开发模式下有"热重载"功能。每次你保存文件,它都会重新运行一遍代码。如果你把 new PrismaClient() 直接写在文件里,每保存一次,就会创建一个新的数据库连接,旧的却没关掉。
  • 解法:使用 单例模式 (Singleton)。把 prisma 实例挂载到 global 全局变量上,防止被重复创建。
    // lib/prisma.ts
    const globalForPrisma = global as unknown as { prisma: PrismaClient }
    
    export const prisma = globalForPrisma.prisma || new PrismaClient()
    
    if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma
    

3. 本章小结

  1. Generate:遇事不决,先跑一遍 npx prisma generate
  2. 6543:在 Serverless 环境,永远连接这个端口 (连接池)。
  3. 转义:别让密码里的特殊字符把你挡在数据库门外。
  4. 单例:Next.js 里必须用 global 缓存 Prisma 实例,否则热重载会把数据库连爆。