代表的な面接トピック

バックエンド面接:データベース接続プールのサイジングと枯渇の診断方法

バックエンド難しい
Offer.cc 編集チーム公開日 更新日

質問

PostgreSQLの最大接続数は500で、そのうち50は運用向けに予約されています。システムには100台のAPIインスタンスと20台のバックグラウンドワーカーがあります。ピーク時には毎秒6,000リクエストを受信し、70%がデータベースにアクセスし、各データベース操作は平均40ミリ秒接続を保持します。プールのサイズ設定、取得タイムアウトの診断、スケーリング、長時間トランザクション、PgBouncerへの対応をどのように行いますか?

問題と範囲

PostgreSQLを使用する注文プラットフォームで、100台のステートレスAPIインスタンスと20台のバックグラウンドワーカーが稼働しています。データベースの max_connections は500に設定されています。マイグレーション、インシデント対応、運用ツール用に50の予約が必要なため、 アプリケーション全体で使用できるバジェットは450接続です。ピークトラフィックは毎秒6,000リクエストで、リクエストの約70%がデータベースに アクセスし、アプリケーショントレースによるとデータベース操作は平均40ミリ秒接続を保持します。 APIリクエストのエンドツーエンドのp99目標は800ミリ秒です。

現在、各プロセスはサイズ10のプールを持っているため、デプロイ全体で理論上 100 × 10 + 20 × 10 = 1,200 のデータベースセッションが作成される可能性があります。ピーク時に接続取得がタイムアウトし始めました。データベースの CPU使用率が55%にとどまることもあれば、ロック待機とクエリレイテンシが同時に上昇することもあります。初期プール割り当て、タイムアウト ポリシー、接続ライフサイクルを設計してください。ローカルプールのサイズ不足、接続リーク、長時間 トランザクション、バジェットを超えるレプリカのスケーリング、データベース内部の過負荷をどのように区別するか説明してください。

インスタンス数、スループット、40ミリ秒の保持時間、500接続の上限は面接用の前提条件であり、PostgreSQL、HikariCP、PgBouncerの 一般的なパフォーマンス主張ではありません。近年のバックエンド面接ガイドラインでは、システム設計におけるパフォーマンス、信頼性、運用上の 考慮事項が引き続き評価されており、2026年にはデータベース接続プール設計に特化した問題が出題されました。中心となるスキルは、アプリケーションの レプリカ全体でデータベースの同時実行性とリソースの所有権を管理することであるため、カテゴリーはバックエンドです。

面接官が評価しているポイント

第1のシグナルは、プールを同時実行制御(アドミッションコントロール)として捉え、接続を増やせばスループットが向上すると安易に仮定しないことです。PostgreSQLの max_connections はデータベース全体の上限であり、これを引き上げるとリソース消費が増加します。1つのインスタンスで独立して設定された 数値は、APIレプリカ、ワーカー、スケジュールジョブ、ローリングリリース中の一時的なレプリカの数を掛け合わせて計算する必要があります。

第2のシグナルは、リトルの法則(Little's Law)を用いてオーダー(桁数)の確認を行い、平均値をそのままキャパシティの 回答として提示しないことです。データベースへの平均到着率は毎秒 6,000 × 70% = 4,200 回の操作です。平均接続占有数は 約 4,200 × 0.04 = 168 です。これは定常状態の平均同時実行数を表しているにすぎません。バースト、p99の保持時間、 ロック待機、トランザクションの再試行、レプリカ間の負荷の偏りには、依然として計測と負荷テストが必要です。

第3のシグナルは、両側の証拠からキューの位置を特定することです。アプリケーション側では、アクティブ数、アイドル数、保留(pending)数、 取得レイテンシとタイムアウト、接続保持時間を公開する必要があります。データベース側では、 pg_stat_activity の状態、wait_event、アクティブクエリ、アイドル状態のトランザクション、接続元を公開する必要があります。「接続取得がタイムアウトした」 という理由だけでプールを拡張すると、キューがアプリケーションからデータベースへと移動するだけになる可能性があります。

最後に、障害境界を定義できているかです。優れた設計では、リクエストのデッドライン、接続リーク、長時間トランザクション、 ローリングリリース、オートスケーリング、データベースの再起動、古い接続(stale connections)、PgBouncerのセッションプーリングと トランザクションプーリングの違いをカバーします。また、トランザクションプーリングでは安全に使用できない可能性のあるセッションスコープの機能についても言及します。

回答前の明確化のための質問

  • 500の上限は単一のプライマリに適用されますか、それともクラスタ全体ですか? リードレプリカ、フェイルオーバー先、運用アクセスには

異なるバジェットがある場合があります。各ワークロードを実際に処理するデータベースごとにプールを個別に計算します。

  • 最大レプリカ数はいくつか? 100台のAPIインスタンスは通常時の数ですか、それともオートスケーリングの最大値ですか?ローリングリリースでは、

新旧のレプリカが一時的に同時に稼働することがあります。定常状態のレプリカのみに基づいた設定では、リリース時やインシデント発生時に バジェットを超過する可能性があります。

  • 接続保持時間の分布はどうなっているか? 平均40ミリ秒という数値からは、p95、p99、トランザクション内のネットワーク呼び出し、

ロック待機などは見えてきません。ロングテールがキューイングとタイムアウトを左右するため、ルート、タスク、トランザクションラベルごとにセグメント化します。

  • バックグラウンド処理はキューイングや同時実行数の制限が可能か? 長時間のバッチジョブが短時間のAPIリクエストと

無制限に競合するべきではありません。プールを分離することは有用ですが、すべてのプールは依然として同じ450のグローバルバジェットを共有します。

  • タイムアウト後にどのような再試行が行われるか? バックオフなしの即時再試行は、データベースが低速化しているまさにそのタイミングで

到着率を増加させます。取得タイムアウトはリクエストのデッドライン内に収まり、アドミッションコントロール、バックオフ、または定義された障害レスポンスと連携する必要があります。

  • アプリケーションはどのセッションスコープ機能を使用しているか? 一時テーブル、LISTEN、セッションアドバイザリロック、

トランザクションをまたぐ SET 状態、プリペアドステートメントの動作は、PgBouncerのトランザクションプーリングが安全かどうかに影響します。

  • 接続プロキシはどこで稼働するか? 単一のPgBouncerインスタンスはキャパシティと可用性の境界となります。

ノードごとのサイドカー、専用のプロキシ層、マネージドプロキシでは障害モードが異なります。

30秒の回答フレームワーク

「まずグローバルバジェットの設定から始めます。500接続のうち50を運用用に予約すると、アプリケーション用には450が残ります。現在の プロセスごとの上限では合計が1,200に膨らみます。平均同時実行数168はスケール感の確認にすぎません。初期割り当てとしては、 各APIインスタンスに2、各ワーカーに4を割り当てて合計280とし、170のヘッドルームを確保した上で、ピーク負荷の下で調整します。取得タイムアウトは 800ミリ秒のリクエストデッドライン内に収める必要があります。プールのpending数、取得レイテンシ、保持時間を、pg_stat_activity および待機イベントと比較します。 データベースに余力があるのにプールでキューが発生している場合は、偏り、リーク、ローカルの上限を確認します。すでにクエリやロックが劣化している場合は、 プールを拡大してはいけません。オートスケーリングではバジェットを再計算する必要があり、PgBouncerのトランザクションプーリングにはセッション状態の監査が必要です。」

ステップバイステップの詳細解説

グローバル接続バジェットの確立

バジェットを明示的な不変条件として記述します。

text
application_connection_cap
  = max_connections
  - operations_reserve
  = 500 - 50
  = 450

すべてのAPI、ワーカー、マイグレーション、管理、ローリングリリースのプール上限の合計は、450以下に保つ必要があります。 他のアプリケーションが同じデータベースを使用している場合は、そのバジェットも差し引きます。運用の予約分は通常トラフィック用の 予備キャパシティではありません。インシデント発生時にデータベースへの接続、監視、修復を行う能力を維持するためのものです。

平均同時実行数の確認は以下の通りです。

text
database_arrival_rate = 6,000 × 70% = 4,200 operations/second
average_in_flight     = 4,200 × 0.04 seconds = 168

これにより、1,200の接続は平均ワークロードから見て正当化できず、全体で20接続では少なすぎる可能性が高いことが素早くわかります。 ただし、平均値はバースト、p99の保持時間、トランザクションの再試行、キューイングのフィードバックを隠してしまうため、最終的なプールサイズを決定するものではありません。 最終的な数値は、サービスのSLO、持続可能なアクティブデータベース同時実行数、負荷テストを組み合わせて決定する必要があります。

テスト可能な初期割り当ての提案

控えめな出発点として、APIインスタンスあたり2接続、ワーカーあたり4接続とします。

text
API cap      = 100 × 2 = 200
worker cap   = 20 × 4  = 80
allocated    = 280
app headroom = 450 - 280 = 170

ワーカーへの4接続という割り当ては、初期の独立した上限にすぎず、「ジョブが長い」ことから直接導かれる値ではありません。 実際の値は、各ワークロードの保持時間分布、到着率、同時実行制限に従う必要があります。280はグローバルバジェットを尊重し、 負荷テストが可能な候補値です。残りの170は自動的に割り当てられるべきではありません。APIレプリカが200に増加した場合、レプリカあたり2を維持すると 400を消費し、ワーカーの80を加えると合計が450を超えてしまいます。スケーリングの際は、インスタンスごとの上限を引き下げるか、最大レプリカ数を制限するか、 プロキシを使用してより集約されたサーバー接続バジェットを強制する必要があります。

すべてのプロセスが常に予備の接続を持てるようにするためだけに、大きな minimumIdle を設定してはいけません。アイドル状態のセッションも グローバル制限を消費します。プールはハード上限までオンデマンドで拡張できます。最小アイドル接続数を保持すべきかどうかは、 測定された接続確立コストとバーストレイテンシに基づいて正当化される必要があります。

取得タイムアウトと接続ライフサイクルの設定

取得タイムアウトは、残りのリクエストデッドラインよりも短く設定する必要があります。p99目標が800ミリ秒の場合、スレッドが 接続待ちで30秒待機することはできません。初期テストでは取得に100〜200ミリ秒を割り当て、測定されたキューの分布に基づいて 調整します。この範囲はシナリオ上の設計選択であり、一般的なライブラリの推奨値ではありません。 タイムアウト後は、識別可能な過負荷エラーを返し、アップストリームのアドミッションコントロールやジッター付きバックオフを使用します。 制限なしに即時再試行を行わないでください。

最大接続ライフサイクルは、データベース、プロキシ、ネットワークによって課される強制的な有効期間よりも短く設定し、 多くの接続が同時に切断されないようにジッターを含める必要があります。Keepaliveは有効であり続けるべきアイドル接続のためのものであり、 最大ライフサイクルよりも頻繁に実行する必要があります。借用(borrow)のたびにすべての接続を検証するとラウンドトリップが増加するため、測定が必要です。 さらに重要なのは、データベースの再起動やフェイルオーバー後の最初のエラー操作を適切に処理し、冪等なビジネス操作のみを再試行することです。

アプリケーションプールがボトルネックかどうかの判断

すべてのプールは、サービス、インスタンス、ワークロードのラベルを付けて、少なくとも以下のメトリクスを公開する必要があります。

  • 設定された最大数、アクティブ数、アイドル数、保留(pending)数
  • p50、p95、p99の取得レイテンシとタイムアウト発生数
  • ルート、タスク、またはトランザクションごとにタグ付けされた接続保持時間
  • 接続の作成、切断、検証失敗、再作成のレート
  • 理論上の合計上限:設定されたプール最大数 × 現在のレプリカ数

単一の値ではなく、組み合わせで解釈します。アクティブ接続が上限に張り付いた状態で保留数と取得レイテンシが増加しており、 データベースには持続可能なアクティブ接続とCPUのヘッドルームがまだある場合、ローカルプールの小ささ、トラフィックの偏り、 または一部の操作が接続を長く保持しすぎていることが考えられます。リクエスト完了後もアクティブな借用数が減少しない場合や、 スタックがアプリケーションコード内に残っている場合は、接続が返却されていない可能性があります。接続の作成と切断の急増は、 ライフサイクルの不一致、プロキシのタイムアウト、またはネットワークの問題を示している可能性があります。

成功、エラー、キャンセル、早期リターンのすべてのパスで確実に接続が解放されるよう、構造化された接続スコープを使用します。 リーク検出のしきい値はパスの特定に役立ちますが、保持時間の分布やコードレビューに代わるものではありません。 しきい値が短すぎると、正当な長時間トランザクションがリークとして誤認されてしまいます。

PostgreSQLの証拠を使用したデータベース過負荷の切り分け

PostgreSQLはサーバープロセスごとに1つの pg_stat_activity 行を公開します。これを application_name、クライアントアドレス、状態、 待機イベントごとにグループ化します。まず以下から始めます。

sql
SELECT application_name, state, wait_event_type, wait_event, count(*)
FROM pg_stat_activity
WHERE datname = current_database()
GROUP BY application_name, state, wait_event_type, wait_event
ORDER BY count(*) DESC;

次に、トランザクション内でアイドル状態になっているセッションを特定します。

sql
SELECT pid, application_name, xact_start, state_change, wait_event_type, wait_event
FROM pg_stat_activity
WHERE state = 'idle in transaction'
ORDER BY xact_start;

接続数の増加に伴いアクティブセッション、クエリレイテンシ、ロック待機、またはI/Oが悪化する場合、ボトルネックはクエリ、 トランザクション、またはデータベースリソースにあります。プールを拡大すると競合が増加するだけです。データベースが500セッション近くに達しているものの、 その多くがアイドル状態のアプリケーションセッションである場合、インスタンスごとのアイドルプールがバジェットを消費しています。これらを縮小するか、 マルチプレキシングを導入します。idle in transaction が継続して発生している場合は、それらのセッションが接続を消費し、 ロックを保持し続けたりバキュームの進行を妨げたりする可能性があるため、トランザクション境界を修正します。

総セッション数は並行実行数と同じではありません。アイドル状態のセッションとロック待ちのセッションでは異なる説明が必要です。 CPU使用率が55%であっても、データベースの余力を証明するものではありません。ロック競合、ストレージレイテンシ、ホットな単一パーティション、 またはシリアルな実行パスにより、全体のCPU使用率が低くても処理がブロックされることがあります。

ワークロードの分離とスケーリングへの対応

短時間のAPIリクエストと長時間のワーカーが1つのプールを共有すると、少数のバッチジョブによってヘッドオブラインブロッキング(先頭ブロッキング)が 発生する可能性があります。このシナリオでの200/80の分割のように、それらに別々のプールと別々の同時実行キューを割り当てます。分離はレイテンシを保護しますが、 バジェットを増やすわけではありません。ワーカープールはアイドル時に縮小できるようにすべきであり、ジョブ自体にも同時実行制限が必要です。

オートスケーラーはデータベースのバジェットを把握している必要があります。最も単純なハード制約は以下の通りです。

text
max_replicas × pool_size_per_replica + other_pool_caps <= 450

ローリングデプロイの maxSurge を含めます。レプリカ数が大きく変動する場合、固定のインスタンスあたりの上限を設定すると、 レプリカ数が少ないときはキャパシティが無駄になり、多いときはバジェットを超過します。小さめの固定プールとリクエストキューイングを併用するか、PgBouncerを使用して 多数のクライアントセッションを制御された数のサーバー接続に多重化します。どちらの方法でも、データベース内部のアクティブな同時実行数は制限し続けます。

PgBouncerを導入すべきかの判断

PgBouncerのセッションプーリングは、クライアントセッションが終了するまで同じサーバー接続を保持します。PostgreSQLの セッション動作との互換性は高いですが、多重化の効果は限定的です。トランザクションプーリングは、トランザクションの期間中のみ サーバー接続を割り当てます。これによりアイドル状態のクライアントがサーバー接続を保持するのを防ぐことができますが、 次のトランザクションが同じサーバーセッションを使用するという前提は崩れます。

トランザクションプーリングを導入する前に、トランザクションをまたぐ SET/RESETLISTEN、セッションアドバイザリロック、一時テーブル、 その他のセッション状態を監査します。アプリケーションがこれらのセマンティクスを必要とする場合は、セッションプーリングを維持するか、特定のパスに個別の 直接接続プールを割り当てるか、状態をトランザクション内に移動します。接続数が減ったという事実だけで成功と判断してはいけません。プロキシの キューイング、プロキシ障害、認証、接続の再作成、データベースのフェイルオーバーをテストします。

障害テストによるキャパシティ検証の完結

段階的な負荷から開始し、毎秒6,000リクエストに向けて引き上げ、その後バーストとオートスケーリングを追加します。各ステップで、 エンドツーエンドのp95/p99、取得レイテンシ、pending数、保持時間、アクティブデータベースセッション数、ロック待機、クエリレイテンシ、 CPU、I/Oを記録します。初期の200/80分割の前後の複数の割り当て候補を比較し、スループットの向上が頭打ちになるポイントや、データベースのレイテンシと キューイングが悪化し始めるポイントを見つけます。

敵対的テスト(Adversarial tests)には、接続を返却しないパスの注入、接続を数秒間保持する複数のトランザクション、ロック競合、 ローリングリリース中に新旧のレプリカが同時に稼働する状態、データベースの再起動、プロキシによる既存サーバー接続の切断、 ワーカーのバックログ急増などを含める必要があります。テストの合格は「エラーがゼロであること」を意味しません。グローバル接続バジェットの下で、 システムがフェイルファストまたはロードシェディング(負荷遮断)を行い、メトリクスによってキューを特定でき、復旧時に接続ストーム(接続の殺到)が発生しないことが条件です。

高品質な回答例

「インスタンスごとの数値を決定する前に、まず500のデータベース接続をバジェットに分割します。運用用に50を 予約すると、アプリケーション用には450が残ります。現在の120プロセスが各10接続を持つ構成では理論上の上限が1,200となり、 ローリングリリースやバースト時にデータベースの上限を超過する可能性があります。

前提条件として、毎秒4,200のデータベース操作があり、平均保持時間は40ミリ秒です。リトルの法則を適用すると、平均で約168の 並行操作となります。これはスケール感の確認としてのみ使用し、p99のキャパシティとは見なしません。初期割り当てとしては、 100台のAPIレプリカにそれぞれ2接続、20台のワーカーにそれぞれ4接続を割り当て、合計280としてアプリケーション用に170のヘッドルームを 残します。実際の保持時間分布、バースト、ロック競合を考慮し、280前後の候補値で負荷テストを行います。オートスケーリングの最大値と ローリングリリースのレプリカ数も計算式に含める必要があります。そうしないと、200台のAPIレプリカとワーカープールで450を超えてしまいます。

取得タイムアウトは800ミリ秒のリクエストデッドライン内に収める必要があります。まずは100〜200ミリ秒でテストを 開始します。アプリケーション側では、アクティブ数、アイドル数、pending数、取得レイテンシ、タイムアウト数、保持時間、接続再作成数を監視します。 PostgreSQL側では、pg_stat_activity をアプリケーション名ごとにグループ化し、アクティブ、アイドル、idle-in-transaction、待機イベントを調査します。 データベースに持続可能なヘッドルームがあるのにプールでキューが発生している場合は、レプリカ間の偏り、ローカル上限、未解放の接続を調査します。 クエリ、ロック、またはI/Oがすでに劣化している場合、プールを拡大してもデータベースの同時実行数が増加するだけです。max_connections 付近のセッションの大半が アイドル状態である場合は、インスタンスごとのアイドルプールを縮小するか、プロキシ経由で多重化します。

短時間のAPIと長時間のワーカーは、合計を450未満に抑えつつ、別々のプールと同時実行制限で分離します。PgBouncerが必要な場合は、 慎重にモードを選択します。セッションプーリングは互換性を維持しやすく、トランザクションプーリングはより強力に多重化できますが、LISTEN、 セッションアドバイザリロック、一時テーブル、トランザクションをまたぐ SET の監査が必要です。最後に、段階的な負荷、バースト、 リーク、長時間トランザクション、ロック競合、ローリングデプロイ、データベース再起動、プロキシ切断を用いて、p99、キューイング、総接続数、復旧性を検証します。」

よくある間違い

  • すべてのインスタンスに一律20接続を割り当てる → レプリカ数が変化したときに総セッション数が制御不能になる →

最初にデータベース全体のバジェットを定義し、それをすべてのプールと最大レプリカ数に配分する。

  • 平均値からきっかり168接続を設定する → バースト、p99保持時間、ロック待機、割り当ての粒度が欠落している →

リトルの法則はスケール感の確認として使用し、分布と負荷テストをもとに決定する。

  • 取得タイムアウトが発生するたびにプールを増やす → アプリケーションのキューイングがデータベースのロック、I/O、CPUのキューに

移動する可能性がある → プールのpending数と、データベースのアクティブセッション、待機イベント、クエリレイテンシを併せて調査する。

  • データベースのCPUのみを確認する → ロック、ストレージレイテンシ、ホットスポットにより、低いCPU使用率でも接続がブロックされることがある →

セッションの状態と待機イベントをもとに解釈する。

  • アイドル接続を無視する → 多数のレプリカにまたがるアイドルプールが先に max_connections を枯渇させる可能性がある →

プールの最大値 × レプリカ数を監視し、最小アイドル接続数を制御する。

  • idle-in-transaction を通常のアイドルとして扱う → トランザクションがロックを保持し、古いスナップショットを維持し、

バキューム処理を妨げる可能性がある → トランザクションの開始点とコード境界を特定し、適切なタイムアウトを適用する。

  • すべてのワークロードを1つのプールにまとめる → 長時間のワーカーが、短時間のAPIに必要な接続を占有してしまう →

グローバルバジェットを超えない範囲で、レイテンシプロファイルごとにプールとキューを分離する。

  • PgBouncerを導入して安易にトランザクションプーリングをデフォルトにする → セッション状態がトランザクション間で消失したり、

別のサーバー接続に移動したりする可能性がある → プーリングモードを選択する前に互換性を監査する。

  • すべての接続エラーを即座に再試行する → データベースの復旧時に接続ストームが発生し、到着率がさらに高くなる →

再試行回数を制限し、ジッター付きバックオフを追加し、冪等な操作のみを再試行する。

  • 定常状態のみをテストする → ローリングリリース、スケーリング、長時間トランザクション、データベース再起動によってバジェットや

ライフサイクルの障害が露呈する → これらを受け入れテストマトリクスに含める。

フォローアップ質問

フォローアップ1:接続を増やすとシステムの処理速度が低下するのはなぜですか?

データベースのCPU、キャッシュ、ロック、ストレージ帯域幅は有限です。持続可能なアクティブ同時実行数を超えると、接続の増加によって コンテキストスイッチ、キャッシュ競合、ロック待機が増加します。各クエリが遅くなり、それによって接続保持時間が延び、 正のフィードバックループ(悪循環)が発生します。小さなプールを使用することでアプリケーション側で制限付きのキューイングが可能になり、 すべてのリクエストをデータベースに流入させるよりも制御が容易になります。ただし、データベースの持続可能なキャパシティを遊ばせてしまうほど プールを小さくしてはいけません。

フォローアップ2:APIが200インスタンスにスケールした場合、何が変わりますか?

インスタンスあたり2接続を維持すると400のAPI接続が生成され、ワーカーの80接続を加えると合計で450を超えてしまいます。 各APIプールを1に減らしてワーカーのバジェットを再配分するか、最大レプリカ数とローリングリリースのサージを制限するか、 PgBouncerを使用してクライアントを多重化します。 決定にあたっては、バースト時のキューイングと持続可能なデータベース同時実行テストを活用します。オートスケーラーは、ダウンストリームの データベースキャパシティを無視してCPUだけを見て判断することはできません。

フォローアップ3:単にクエリが遅いのではなく、リークであることをどのように証明しますか?

リークは多くの場合、アクティブな借用数が増加し続けること、恒常的な保留リクエストが存在すること、リクエスト自体はすでに終了しているのに データベースセッションがアイドル状態で残っていることとして現れます。各借用をルート、タスク、サンプリングされたスタックに関連付け、保持時間と リクエストの有効期間を比較し、例外パス、キャンセルパス、早期リターンパスを調査します。PostgreSQLのセッションがアクティブなままであるか ロック待ちである場合は、リークと判断する前にクエリとトランザクションの原因を解明してください。

フォローアップ4:HikariCPのプールサイズ計算式をそのまま適用できますか?

(core_count × 2) + effective_spindle_count はHikariCPのドキュメントにおける初期のヒューリスティックであり、ドキュメント自体にも これをもとに負荷テストを行うよう明記されています。SSD、キャッシュヒット率、クエリタイプ、リモートデータベースの存在によって結果は変化します。 さらに重要な点として、1つのデータベースを多数のアプリケーションレプリカで共有している場合、データベースレベルの候補値であっても 各レプリカに配分する必要があります。この計算式は、450というグローバルバジェットや実際のSLOの根拠に代わるものではありません。

フォローアップ5:PgBouncerのトランザクションプーリングでは、プリペアドステートメントは常にサポートされませんか?

すべてのバージョンや設定において絶対的な主張をしてはいけません。デプロイされているバージョン、プロトコルレベルのプリペアドステートメントの サポート、ドライバの設定に照らしてPgBouncerの機能マトリクスを検証してください。トランザクションプーリングでは、2つのトランザクションが 同じサーバーセッションを使用することは依然として保証されません。アプリケーションが依存している実際のセッションセマンティクスを洗い出し、 統合テストで検証した上で、パスごとにトランザクションプーリング、セッションプーリング、または直接プールを選択してください。

フォローアップ6:プールを増やした後に取得レイテンシは下がったが、エンドツーエンドのp99が悪化しました。なぜですか?

キューがアプリケーションプールからデータベース内部へと移動したためです。より多くのクエリが同時に投入されることで、ロック競合、I/O、 またはCPUのキューイングによってクエリの実行時間が長くなります。取得メトリクスが改善したからといって、ユーザーから見たレイテンシが改善したとは 限りません。エンドツーエンドのp99、データベースクエリ実行時間、待機イベント、スループットを比較し、合計レイテンシが最も低く、 安定したヘッドルームが得られる同時実行ポイントを選択してください。

公開情報ソース

関連する質問