跳至主要内容

使用 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 devprisma db push)被调用时,将使用此连接字符串。

PgBouncer 与不同的数据库提供商

直接连接到 Postgres 数据库的方式有时会有细微的差异,具体取决于托管数据库的提供商。

以下链接提供了有关如何使用这些提供商设置这些连接的信息,这些提供商的设置步骤不在我们的文档中介绍。

Supabase Supavisor

Supabase 的 Supavisor 的行为类似于 PgBouncer。您可以通过您可用的 Supabase 数据库设置?pgbouncer=true 添加到您的连接池连接字符串中。

其他外部连接池

虽然 Prisma ORM 没有明确支持其他连接池,但如果限制与 PgBouncer 的限制类似,您通常也可以在您的连接字符串中使用 pgbouncer=true 来将 Prisma ORM 置于与它们协同工作的模式中。