跳到主要内容

连接池

查询引擎管理数据库连接的连接池。连接池在 Prisma Client 打开与数据库的首次连接时创建,这可以通过以下两种方式之一发生

关系数据库连接器使用 Prisma ORM 自己的连接池,而 MongoDB 连接器使用 MongoDB 驱动程序连接池

关系数据库

关系数据库连接器使用 Prisma ORM 的连接池。连接池具有连接限制连接池超时,这些都由连接 URL 参数控制。

连接池的工作原理

以下步骤描述了查询引擎如何使用连接池

  1. 查询引擎实例化一个连接池,其中包含可配置的池大小池超时
  2. 查询引擎创建一个连接并将其添加到连接池。
  3. 当查询进入时,查询引擎从池中预留一个连接来处理查询。
  4. 如果连接池中没有空闲连接可用,则查询引擎会打开额外的数据库连接并将其添加到连接池,直到数据库连接数达到 connection_limit 定义的限制。
  5. 如果查询引擎无法从池中预留连接,则查询将添加到内存中的 FIFO(先进先出)队列。FIFO 意味着查询按照它们进入队列的顺序进行处理。
  6. 如果查询引擎在时间限制之前无法处理队列中的查询,则会为该查询抛出错误代码为 P2024 的异常,并继续处理队列中的下一个查询。

如果您经常遇到池超时错误,则需要优化连接池

连接池大小

默认连接池大小

默认连接数(池大小)使用以下公式计算

num_physical_cpus * 2 + 1

num_physical_cpus 表示您的应用程序运行的机器上的物理 CPU 数量。如果您的机器有四个物理 CPU,则您的连接池将包含九个连接 (4 * 2 + 1 = 9)。

虽然该公式代表了一个良好的起点,但推荐的连接限制还取决于您的部署范例 - 特别是如果您正在使用 serverless。

设置连接池大小

您可以通过在数据库连接 URL 中显式设置 connection_limit 参数来指定连接数。例如,在您的Prisma schema中使用以下 datasource 配置,连接池将恰好有五个连接

datasource db {
provider = "postgresql"
url = "postgresql://johndoe:mypassword@localhost:5432/mydb?connection_limit=5"
}

查看连接池大小

Prisma Client 使用的连接数可以使用日志记录指标查看。

使用 info 日志记录级别,您可以记录在实例化 Prisma Client 时打开的连接池中的连接数。

例如,考虑以下 Prisma Client 实例和调用

import { PrismaClient } from '@prisma/client'

const prisma = new PrismaClient({
log: ['info'],
})

async function main() {
await prisma.user.findMany()
}

main()
显示CLI结果
prisma:info Starting a postgresql pool with 21 connections.

PrismaClient 类被实例化时,日志记录通知 stdout 启动了一个包含 21 个连接的连接池。

警告

请注意,log: ['info'] 生成的输出可能会在任何版本中更改,恕不另行通知。如果您依赖于应用程序或您正在构建的工具中的输出,请注意这一点。

如果您需要更深入地了解连接池的大小以及正在使用和空闲连接的数量,您可以使用指标功能(目前处于预览版)。

考虑以下示例

import { PrismaClient } from '@prisma/client'

const prisma = new PrismaClient()

async function main() {
await Promise.all([prisma.user.findMany(), prisma.post.findMany()])

const metrics = await prisma.$metrics.json()
console.dir(metrics, { depth: Infinity })
}

main()
显示CLI结果
{
"counters": [
// ...
{
"key": "prisma_pool_connections_open",
"labels": {},
"value": 2,
"description": "Number of currently open Pool Connections"
}
],
"gauges": [
// ...
{
"key": "prisma_pool_connections_busy",
"labels": {},
"value": 0,
"description": "Number of currently busy Pool Connections (executing a datasource query)"
},
{
"key": "prisma_pool_connections_idle",
"labels": {},
"value": 21,
"description": "Number of currently unused Pool Connections (waiting for the next datasource query to run)"
},
{
"key": "prisma_pool_connections_opened_total",
"labels": {},
"value": 2,
"description": "Total number of Pool Connections opened"
}
],
"histograms": [
/** ... **/
]
}
信息

有关指标输出中可用内容的更多详细信息,请参阅关于指标部分。

连接池超时

默认池超时

默认连接池超时为 10 秒。如果查询引擎在该时间内未从数据库连接池获取连接,则会抛出异常并继续处理队列中的下一个查询。

设置连接池超时

您可以通过在数据库连接 URL 中显式设置 pool_timeout 参数来指定池超时。在以下示例中,池在 2 秒后超时

datasource db {
provider = "postgresql"
url = "postgresql://johndoe:mypassword@localhost:5432/mydb?connection_limit=5&pool_timeout=2"
}

禁用连接池超时

您可以通过将 pool_timeout 参数设置为 0 来禁用连接池超时

datasource db {
provider = "postgresql"
url = "postgresql://johndoe:mypassword@localhost:5432/mydb?connection_limit=5&pool_timeout=0"
}

您可以选择禁用连接池超时,如果查询必须保留在队列中 - 例如,如果您要并行导入大量记录,并且确信队列不会在作业完成之前耗尽所有可用 RAM。

MongoDB

MongoDB 连接器不使用 Prisma ORM 连接池。连接池由 MongoDB 驱动程序在内部管理,并通过连接字符串参数配置

外部连接池

您无法将 connection_limit 增加到超出底层数据库可以支持的范围。这在 serverless 环境中尤其具有挑战性,在 serverless 环境中,每个函数管理着 PrismaClient 的一个实例 - 及其自己的连接池。

考虑引入像 PgBouncer 这样的外部连接池,以防止您的应用程序或函数耗尽数据库连接限制。

手动数据库连接处理

当使用 Prisma ORM 时,数据库连接在引擎级别处理。这意味着它们不会暴露给开发人员,并且无法手动访问它们。