实例化 PrismaClient 与连接池管理
基本用法
import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient()
就这一行。创建 PrismaClient 实例时,它不会立刻连接数据库——连接池是懒加载的,第一次执行查询时才建立。
开发环境的热重载问题
如果你用 Next.js、Remix、或其他支持 HMR(热模块替换)的开发服务器,每次文件变更都会重新执行整个模块。这会导致:
- 每次 HMR 都创建一个新的
PrismaClient实例 - 旧实例的连接没有关闭
- 连接数快速耗尽,报错
P1001: Can't reach database server
解决方案:全局单例
在一个单独的 prisma.ts 文件里:
// src/lib/prisma.ts
import { PrismaClient } from '@prisma/client'
const globalForPrisma = globalThis as unknown as {
prisma: PrismaClient | undefined
}
export const prisma =
globalForPrisma.prisma ??
new PrismaClient({
log: process.env.NODE_ENV === 'development' ? ['query', 'error', 'warn'] : ['error'],
})
if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma
然后在任何文件里 import { prisma } from './lib/prisma' 就能用了。
逻辑是:
- 生产环境每次启动正常创建一个实例
- 开发环境把实例存到
globalThis上,HMR 后复用上一个实例 log参数在开发时打印 SQL 查询日志,方便调试
连接池参数
new PrismaClient() 可以传连接池配置:
const prisma = new PrismaClient({
datasourceUrl: process.env.DATABASE_URL,
log: ['query', 'info', 'warn', 'error'],
})
连接池大小通常由 datasource URL 的参数 控制,而不是 PrismaClient 构造参数:
postgresql://user:pass@host:5432/dbname?connection_limit=5&pool_timeout=20
| 参数 | 含义 | 默认值 |
|---|---|---|
connection_limit | 最大连接数 | 取决于数据库(PostgreSQL 通常默认 10~20) |
pool_timeout | 获取新连接的超时时间(秒) | 10 |
长驻进程 vs 一次性脚本
| 场景 | 做法 |
|---|---|
| Web 服务器、API 服务 | 创建一个实例,整个应用生命周期复用,不要 $disconnect() |
| CLI 工具、定时任务、脚本 | 创建实例,用完后 .finally(() => prisma.$disconnect()) |
一次性脚本如果不手动 $disconnect(),Node.js 进程会因为连接池还有活跃连接而不退出。
$connect() 主动连接
默认情况下 Prisma Client 懒连接。如果你需要在应用启动时就探活数据库(比如启动前的健康检查):
await prisma.$connect()
失败会抛错,方便你在启动阶段就知道数据库连不上,而不是等到第一个请求才爆。