Prisma 查询能用,迁移报 prepared statement s0 already exists:分开池化与直连地址
Prisma 业务查询正常,迁移通过 PgBouncer 报 prepared statement s0 already exists 时,分开 CLI 直连与运行时池化地址,核对 Prisma 版本及失败迁移状态。
应用通过 PgBouncer 能执行 Prisma 查询,但部署中的 prisma migrate 报 prepared statement "s0" already exists,或 PostgreSQL 状态码 42P05。如果迁移也使用了同一个事务池地址,应先把迁移连接与运行时连接分开检查。
这个错误也可能发生在其他预编译语句场景。本文限定于 Prisma Migrate 经 PgBouncer 的路径,不能凭 s0 报错就删除迁移记录、清空数据库或重新生成迁移。
检查迁移进程实际采用的地址
查看出错阶段是 Prisma Client 的业务查询,还是 CLI 的 Migrate、db push 等操作。记录 Prisma、驱动或 adapter、PgBouncer 的版本和连接池模式,再核对当前发布进程加载的环境变量及配置文件。
池化端口与数据库直连端口可能不同,不能根据主机名相同判断这就是直连。应使用数据库服务提供的完整直连信息,包括用户名、数据库、端口和 TLS 参数;不要假设所有服务都用 5432。
Prisma Schema Engine 需要单连接语义,Prisma 对 PgBouncer 的迁移处理方式是让 CLI 走直连,而运行时继续走池化路径。不要为了迁移就把应用所有请求切为直连,那可能增加数据库连接压力。
Prisma 7:CLI 在 prisma.config.ts 里使用直连
以下是已经采用 Prisma ORM 7 配置方式的片段示例。DIRECT_URL 应由部署环境安全注入为直连字符串,DATABASE_URL 保留运行时池化字符串;不要把实际密码提交到仓库:
import "dotenv/config";
import { defineConfig, env } from "prisma/config";
export default defineConfig({
schema: "prisma/schema.prisma",
datasource: {
url: env("DIRECT_URL"),
},
});
合并进现有配置,保留项目的 migrations 路径等其他选项。使用 .env 时,示例要求项目已有 dotenv 并能加载正确的文件;平台直接注入环境变量时,也应确认 CLI 能取得它们。
运行时的 driver adapter 则继续使用池化连接。例如采用 @prisma/adapter-pg 的项目,应核对其 connectionString 取的是运行时变量,而不是上述 CLI 的直连变量。不要照抄一条环境变量名,却让两个入口最终仍指向同一个池化端口。
旧项目不要直接照搬新字段
Prisma 7 的配置与旧项目不同。Prisma 6 中支持 directUrl 的项目,可以在对应 datasource 配置中保留运行时 url,让需要直连的 CLI 使用 directUrl;Prisma 7 已移除配置中的 datasource.directUrl,CLI 使用 datasource.url。
更老版本没有同样的配置能力时,应按该版本支持的方式给受控迁移进程提供直连地址,或先完成兼容升级。不要用拼接数据库密码的 shell 脚本临时替换所有环境变量,也不要在多实例启动时都自动并发运行迁移。
pgbouncer=true 主要涉及客户端与旧池化版本的兼容,不能作为 Migrate 的直连替代。PgBouncer 1.21 起,在 max_prepared_statements 非零时支持事务池中的协议级预编译语句;不能继续套用“所有 PgBouncer 都不支持预编译”的旧结论。运行时参数还需与 Prisma/adapter 及实际池化版本匹配。
重试前确认迁移有没有已经改变数据库
配置更换前保存原配置和目标数据库备份,核对失败迁移状态及已经执行的 SQL。更换地址不会撤销先前执行过的结构变更;不能只看到报错就认定数据库完全没有变化。
按项目既有部署流程确认迁移状态后,再决定重试或处理失败迁移。不要为消除错误删除 _prisma_migrations、执行生产重置或改成关闭 TLS。直连可能需要额外网络访问,但开放范围应只覆盖获准的迁移执行环境。
验收应同时确认 CLI 使用直连、预期迁移状态正确,以及应用仍使用设计中的池化路径并能完成业务查询。恢复旧配置不会自动回滚数据库结构,结构变更要按对应迁移的回退或前向修复方案处理。


