05. 数据库集成与 ORM 最佳实践
在 Next.js 全栈开发中,数据库连接与传统的 Node.js 服务(如 Express 常驻内存)完全不同。
由于 Next.js API Routes 和 Server Actions 经常运行在 Serverless (无服务器) 环境中,函数执行完就会销毁。如果每次请求都创建一个新的数据库连接,高并发下会瞬间耗尽数据库连接数,导致应用崩溃。
1. 核心问题:连接池耗尽 (Connection Exhaustion)
❌ 错误写法:
// lib/db.ts
import { PrismaClient } from '@prisma/client'
// 😱 每次 import 这个文件,都会 new 一个新的连接实例
// 在开发环境(热更新)或 Serverless 环境下,这会导致连接数无限增长
export const db = new PrismaClient()✅ 正确写法:全局单例模式
我们需要把客户端实例挂载到 globalThis 对象上,确保整个进程只存在一个实例。
// lib/db.ts
import { PrismaClient } from '@prisma/client'
// 1. 声明全局类型,防止 TS 报错
const globalForPrisma = globalThis as unknown as {
prisma: PrismaClient | undefined
}
// 2. 如果已有实例则复用,否则新建
export const db = globalForPrisma.prisma ?? new PrismaClient()
// 3. 在非生产环境下,将实例保存到全局变量
if (process.env.NODE_ENV !== 'production') {
globalForPrisma.prisma = db
}这样,无论 Next.js 在开发环境怎么热重载 (Hot Reload),数据库连接始终只有一个。
2. ORM 选型建议
在 2024/2025 年,Next.js 生态主要流行两个 ORM:
| 特性 | Prisma | Drizzle ORM |
|---|---|---|
| 风格 | 面向对象,Schema 优先 (schema.prisma) | 函数式,TS 代码优先 |
| 类型安全 | ⭐️⭐️⭐️⭐️⭐️ (自动生成) | ⭐️⭐️⭐️⭐️⭐️ (基于 TS 推断) |
| 性能 | ⚠️ 较重 (基于 Rust Binary) | 🚀 极轻 (SQL wrapper) |
| 冷启动 | 较慢 | 极快 (适合 Serverless) |
| 适用场景 | 传统企业级项目,快速开发,不极致追求冷启动速度 | Serverless Edge 环境,追求极致性能 |
Prisma 快速上手示例
-
安装
npm install prisma --save-dev npm install @prisma/client npx prisma init -
定义模型 (
prisma/schema.prisma)model User { id String @id @default(cuid()) email String @unique posts Post[] } model Post { id String @id @default(cuid()) title String published Boolean @default(false) authorId String author User @relation(fields: [authorId], references: [id]) } -
同步数据库
npx prisma db push -
在 Server Component 中使用
// app/page.tsx import { db } from '@/lib/db' export default async function Page() { const posts = await db.post.findMany({ where: { published: true }, include: { author: true } }) return ( <ul> {posts.map(post => ( <li key={post.id}>{post.title} by {post.author.email}</li> ))} </ul> ) }
3. Serverless 环境下的特殊处理
如果你的数据库(如 MySQL/PostgreSQL)托管在传统云服务器上,而 Next.js 部署在 Vercel Edge 或 AWS Lambda 上,你需要使用 连接池代理 (Connection Pooling)。
- Vercel Postgres / Neon: 自带 Serverless Driver,无需担心。
- PlanetScale: 使用 HTTP 协议,无连接数限制。
- AWS RDS / 自建数据库: 必须配合 Prisma Data Proxy 或 PgBouncer 使用,否则并发一高就会挂。
4. 总结
- 必须使用单例模式:防止开发环境和 Serverless 环境连接泄露。
- Server Component 直连:在 Server Component 中直接查数据库是最高效的,不需要经过 fetch API。
- 注意环境限制:如果部署在 Edge Runtime,Prisma 可能不兼容(因为它依赖 Node.js API),此时推荐用 Drizzle 或 Prisma Accelerate。