11
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Prisma の connection pool の設定あれこれ

Posted at

Prisma の connection pool

Prisma の connection pool のデフォルト値は、CPU の数で決まっている。

CPUの数 x 2 + 1

CPU が1つなら、3だ。

Prisma の connection pool timeout は、10秒。

via. Connection pool

上限値の変更方法

DATABASE_URL で指定する。

DATABASE_URL="mysql://${DB_USER}:${DB_PASS}@${DB_HOST}/${DB_NAME}?schema=public&connection_limit=30&pool_timeout=60"

こんな感じで指定するだけ。
当然、CPU への負荷は上がるので、根本的には、CPU の数を増やすのが良い。予算やインフラチームと相談しよう。
テストサーバで、大量に seed したい時とか、そういう時に使うのが良い。

via. Connection pool

Transaction の場合

Transaction APIを使うと、ちょっと負荷をかけると Transaction API error: Transaction not found と言うようなエラーが出る。あれこれ調べると、3.9 で解消しているとされているが、それ以上のバージョンでやっても出る。これは、どうやら Transaction API の maxWaittimeout を指定してあげれば解決するらしい。maxWait のデフォルト値は2秒、timeout は5秒

await prisma.$transaction(
  async (tx) => {
    // Code running in a transaction...
  },
  {
    maxWait: 5000, // default: 2000
    timeout: 10000, // default: 5000
  }
)

via. Transactions and batch queries

が、これやってもダメなこともあるようだ。previewFeature 卒業してる 4 系の最新バージョンを使うと改善されているのかも知れない。(試してない)

そもそもの接続を減らす

warn(prisma-client) There are already 10 instances of Prisma Client actively running.

こういう警告が出る。警告が出ても Local では問題なく動くが、Production build で connection pool の上限に引っかかってエラーになることがある。
これは、new PrismaClient() するたびに増えていくため、1度だけ呼ぶようにする。
具体的には、lib/prisma.ts などを作成し、それを必要なところで呼ぶようにする。

lib/prisma.ts
import { PrismaClient } from '@prisma/client';

const globalForPrisma = global as unknown as { prisma: PrismaClient };

export const prisma =
  globalForPrisma.prisma ||
  new PrismaClient();

if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma;
pages/api/index.tsx
import { prisma } from '../../lib/prisma.ts';

export const ....
 const hoge = await prisma.moge.findMany({...})
...

こんな感じで。

via. Best practice for instantiating PrismaClient with Next.js

$disconnect() すべきなのか?

これは、ケースバイケースだとしか言いようがないが、私が Next.js でよく作っている API のようなアプリケーションの場合、やらない方が良いようだ。

$disconnect()を呼び出すと , Prisma Clientは、

  1. beforeExit hook を実行します
  2. Query Engine の子プロセスを終了し、全ての接続を閉じます

GraphQL API のような長時間稼働するアプリケーションでは、常にリクエストを処理するため、各リクエストの後に $disconnect() を実行する意味がありません。 - 接続の確立に時間がかかるため、各リクエストで接続を切断すると、アプリケーションの速度が低下します。

長時間実行するアプリケーションでは、接続数が多くなりすぎないように、アプリケーション全体で単一の PrismaClient のインスタンスを使用することをお勧めします。

via. Connecting and disconnecting

とあるので、API のようなアプリケーションでは、$disconnect() を呼び出すのは良くない。
逆に、テスト等で、終わったらきちんと切断したい場合は、明示的に $disconnect() を呼ぶ。

まとめ

  • Connection pool の上限は、CPU で決まるので、実行するサーバのスペックを検討する
  • 一時的に接続数を増やしたいなどの場合は、DATABASE_URL で指定する
  • Transaction は、個別に指定する
  • シングルインスタンスを使う
  • $disconnect() は API のようなサービスの場合は、しない。
11
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?