数据库连接失败:P1001、P1002、SSL 问题排查
Prisma 连接错误码速查
| 错误码 | 含义 | 排查方向 |
|---|---|---|
| P1001 | Can't reach database server | 网络/DNS/防火墙 |
| P1002 | Database server connection timeout | 连接池满/服务器负载高 |
| P1003 | Database file not found(SQLite) | 文件路径不对 |
| P1008 | Operations timed out | 操作本身太慢,加 timeout |
| P1017 | Server closed the connection | 数据库重启/连接数超限 |
| P1020 | SSL 连接需要 | Serverless 平台常见,加 sslmode |
排查步骤(从简到难)
第一步:直接用数据库客户端连
# PostgreSQL
psql "postgresql://user:pass@host:5432/dbname"
# MySQL
mysql -h host -u user -p dbname
# SQLite
sqlite3 prisma/dev.db
如果数据库客户端也连不上,那问题在数据库本身或网络,不是 Prisma。
第二步:检查 DNS
# 看数据库主机名能不能解析
nslookup your-db-host.example.com
# 或
ping your-db-host.example.com
Vercel / Railway 等平台上的 Neon、Supabase 托管数据库偶尔会有 DNS 问题。
第三步:检查防火墙
- 本地机器的防火墙有没有出站拦截数据库端口
- 云数据库的安全组/白名单有没有放你当前 IP
- Serverless 平台(Vercel Functions)的出口 IP 可能变——建议数据库白名单设宽一点或用 Accelerate
第四步:加 SSL
Serverless 平台上的云数据库几乎都强制 SSL 连接。在连接串里加:
# PostgreSQL
postgresql://user:pass@host:5432/dbname?schema=public&sslmode=require
# MySQL
mysql://user:pass@host:3306/dbname?sslmode=required
如果 Prisma 报 P1020,大概率是缺 SSL。
第五步:检查 Direct URL
如果你用了 Accelerate 或其他连接池代理,确保:
DATABASE_URL指向连接池(应用运行走这里)DIRECT_URL指向真正的数据库(migrate/db pull/studio 走这里)
没有 DIRECT_URL 时 CLI 命令会尝试走连接池,可能报连接失败或锁表超时。
第六步:连接池耗尽
如果报的是 P1002(超时)或 P1017(服务器主动断连),很可能是数据库连接数满了。
-- PostgreSQL 查当前连接数
SELECT count(*) FROM pg_stat_activity;
-- 查连接上限
SHOW max_connections;
解决:
- 加连接池(Accelerate / PgBouncer / Supavisor)
- 应用侧减小
connection_limit - 增加数据库
max_connections(有些云平台可以在控制台改)
第七步:Neon / Supabase 特定
Neon 有特殊注意:
- Pooler 连接串后缀是
-pooler,普通后缀的连接串直连 - 不要同时用两个后缀
# Neon Pooler 连接(应用运行)
postgresql://user:pass@ep-xxx-pooler.us-east-2.aws.neon.tech/neondb
# Neon 直连(migrate / CLI 用)
postgresql://user:pass@ep-xxx.us-east-2.aws.neon.tech/neondb
Supabase:
- Supabase 连接串里要加
?sslmode=require - Supabase 免费版 7 天不活动会暂停,需要手动在控制台 resume
数据库 URL 格式错误
常见手误:
| 错误 | 正确 |
|---|---|
postgresql://localhost/mydb?schema=public | postgresql://postgres:password@localhost:5432/mydb?schema=public(漏了密码和端口) |
mysql://root@localhost:3306/mydb | mysql://root:password@localhost:3306/mydb(漏了密码) |
SQLite 写成 sqlite:///dev.db | Prisma 用 file:./dev.db |
Prisma CLI 报错时会打印你配置的 DATABASE_URL 的一部分(会隐藏密码),检查一下是不是格式有问题。
prisma doctor
Prisma 自带一个诊断命令:
npx prisma doctor
它会检查:
- Prisma CLI 和 @prisma/client 版本是否匹配
- DATABASE_URL 格式是否合法
- 数据库是否可连(用
$queryRaw跑一条简单查询) - Schema 是否能被正确解析
这个命令输出的信息比普通报错更详细,遇到连接问题先跑一下。