跳至主要内容

连接池

查询引擎管理一个连接池,其中包含数据库连接。池是在 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)。

虽然公式代表了一个良好的起点,但推荐的连接限制也取决于您的部署模式,尤其是在您使用无服务器的情况下。

设置连接池大小

您可以通过在数据库连接 URL 中显式设置connection_limit参数来指定连接数。例如,使用您Prisma 架构中的以下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增加到超出底层数据库所能支持的范围。这在无服务器环境中是一个特别的挑战,因为每个函数都会管理一个PrismaClient实例及其自己的连接池。

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

手动数据库连接处理

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