使用 PgBouncer 配置 Prisma Client
像 PgBouncer 这样的外部连接池持有与数据库的连接池,并在 Prisma Client 和数据库之间充当代理,通过代理传入的客户端连接。这减少了数据库在任何给定时间必须处理的进程数量。
通常,这可以透明地工作,但某些连接池只支持有限的功能集。外部连接池不支持的一种常见功能是命名预处理语句,Prisma ORM 使用这种语句。对于这些情况,可以配置 Prisma ORM 以不同方式执行。
PgBouncer
将 PgBouncer 设置为事务模式
为了使 Prisma Client 可靠地工作,PgBouncer 必须在 事务模式 下运行。
事务模式为每个事务提供一个连接 - 这是 Prisma Client 与 PgBouncer 协同工作的要求。
在连接 URL 中添加 pgbouncer=true
要将 Prisma Client 与 PgBouncer 一起使用,请在 PostgreSQL 连接 URL 中添加 ?pgbouncer=true
标志。
postgresql://USER:PASSWORD@HOST:PORT/DATABASE?pgbouncer=true
注意:为 PgBouncer 池指定
PORT
有时不同于默认的5432
端口。请查看您的数据库提供商文档以获取正确的端口号。
pgbouncer
模式在 Prisma ORM 中的工作原理
- Prisma ORM 为每个查询打开一个事务 - 即使只是读取数据,也允许 Prisma 使用预处理语句。
- Prisma ORM 不会尝试设置
search_path
,因为 PgBouncer 不支持它。 - Prisma ORM 通过在准备和执行 Prisma Client 查询之前运行
DEALLOCATE ALL
来清理连接中已存在的预处理语句。 - Prisma ORM 还禁用任何预处理语句或类型查询缓存。
Prisma Migrate 和 PgBouncer 解决方法
Prisma Migrate 使用数据库事务来检查数据库的当前状态和迁移表。但是,架构引擎被设计为使用单个数据库连接,并且不支持使用 PgBouncer 进行连接池。如果您尝试在使用 PgBouncer 进行连接池的任何环境中运行 Prisma Migrate 命令,您可能会看到以下错误。
Error: undefined: Database error
Error querying the database: db error: ERROR: prepared statement "s0" already exists
要解决此问题,您必须直接连接到数据库,而不是通过 PgBouncer。为此,您可以使用 directUrl
字段,位于您的 datasource
块中。
例如,请考虑以下 datasource
块。
datasource db {
provider = "postgresql"
url = "postgres://USER:PASSWORD@HOST:PORT/DATABASE?pgbouncer=true"
directUrl = "postgres://USER:PASSWORD@HOST:PORT/DATABASE"
}
上面的块使用 PgBouncer 连接字符串作为主要 URL,使用 url
,允许 Prisma Client 利用 PgBouncer 连接池。
它还使用 directUrl
字段提供直接到数据库的连接字符串,没有 PgBouncer。当需要单个数据库连接的命令(如 prisma migrate dev
或 prisma db push
)被调用时,将使用此连接字符串。
PgBouncer 与不同的数据库提供商
直接连接到 Postgres 数据库的方式有时会有细微的差异,具体取决于托管数据库的提供商。
以下链接提供了有关如何使用这些提供商设置这些连接的信息,这些提供商的设置步骤不在我们的文档中介绍。
Supabase Supavisor
Supabase 的 Supavisor 的行为类似于 PgBouncer。您可以通过您可用的 Supabase 数据库设置 将 ?pgbouncer=true
添加到您的连接池连接字符串中。
其他外部连接池
虽然 Prisma ORM 没有明确支持其他连接池,但如果限制与 PgBouncer 的限制类似,您通常也可以在您的连接字符串中使用 pgbouncer=true
来将 Prisma ORM 置于与它们协同工作的模式中。