Heroku Postgres のサーバー側接続プール
この記事の英語版に更新があります。ご覧の翻訳には含まれていない変更点があるかもしれません。
最終更新日 2024年02月14日(水)
Heroku Postgres のサーバー側接続プールは、接続制限やメモリ不足エラーを回避するためにアプリケーションがデータベース接続を効率的に使用するのに役立ちます。これにより、独自の接続プールを保持するサービスである pgbouncer
経由でデータベースに接続できるようになります。pgbouncer
は、すでに開かれているデータベース接続に対して直接クエリを実行するため、データベースサーバーによって新しいプロセスが作成される頻度が削減されます。
pgbouncer
の接続プールはデータベースサーバー上に存在するため、ユーザーのアプリと、データベースと通信している外部アプリの両方が同じプールを共有できます。
クライアント側接続プールについては、「dyno での PgBouncer の実行」を参照してください。
接続プールの可用性の確認
データベースで接続プールが使用可能かどうかを確認するには、heroku pg:info
コマンドを使用します。使用可能な場合は、Connection Pooling
フィールドが Available
と表示されます。
$ heroku pg:info
=== DATABASE_URL
Plan: Private 2
Status: Available
HA Status: Available
Data Size: 2.23 GB
Tables: 83
PG Version: 10.1
Connections: 26/400
Connection Pooling: Available
古い Heroku Postgres インスタンスで使用不可
依存関係が存在しないため、Heroku Postgres の一部の古いインスタンスでは接続プールを使用できません。接続プールがデータベースで現在使用できない場合は、この手順を使用してそれを更新できます。 詳細は、「Updating Heroku Postgres Databases」(Heroku Postgres データベースの更新) を参照してください。
サーバー側接続プールは、Essential 層のデータベースでは使用できません。クライアント側接続プールについては、「dyno での PgBouncer の実行」を参照してください。
接続プールの有効化
次のコマンドを使用して、データベースの接続プールをアクティブにできます。
$ heroku pg:connection-pooling:attach DATABASE_URL --as DATABASE_CONNECTION_POOL
このコマンドにより、DATABASE_CONNECTION_POOL_URL
(つまり、--as
オプションで指定した名前に _URL
が追加されたもの) という名前の環境設定が追加されます。ここに、アプリは他の Postgres URL と同様に接続できます。
デフォルト名の DATABASE_CONNECTION_POOL_URL
を使用することをお勧めします。この名前の接続プーラーは、Postgres バージョンのアップグレード中、または
プランの変更時に新しいリーダーに自動的に再アタッチされます。
現時点では、複数のプールはサポートされていません。必要な場合、複数の名前で接続プールをアタッチできますが、それらは同じ PgBouncer プールを指します。
接続プールを使用して Heroku Postgres を別のアプリと共有するには、そのアプリと PostgreSQL アドオンを共有し、共有されるアプリ内でプール URL を取得する必要があります。それにより、接続情報を環境設定 DATABASE_CONNECTION_POOL_URL
から入手できます。
アプリケーションでの接続プールの使用
多くのフレームワークでは、データベースに接続するために DATABASE_URL
環境変数を自動的に使用します。そのため、アプリケーションが接続プーラーに接続するには、この変数を上書きする必要があります。たとえば、config/database.yml
内の Ruby on Rails は次のようになります。ここで、接続プールアタッチメントは DATABASE_CONNECTION_POOL_URL
です。
production:
url: <%= ENV['DATABASE_CONNECTION_POOL_URL'] || ENV['DATABASE_URL'] %>
prepared_statements: false
接続プールの削除
接続プールアタッチメントは、次のコマンドを使用して削除できます。そのアタッチメントはデータベースに接続できなくなるため、アプリケーションで使用しないようにしてください。
$ heroku addons:detach DATABASE_CONNECTION_POOL --app example-app
接続プールの統計の表示
Heroku Postgres の接続プールの統計を pgbouncer の内部データベースから取得できます。
接続プールの統計は、psql
経由で pgbouncer
の内部データベースから取得できます。dyno 内から Postgres に接続する必要があります。接続プールのデータベース URL を取得し、次のように、そのパスの最後のコンポーネントを /pgbouncer
に置き換えます。
% heroku run bash -a example-app
Running bash on ⬢ example-app... up, run.7383 (Private-M)
$ psql postgres://username:password@ec2-192-168-1-1.compute-1.amazonaws.com:5433/pgbouncer?sslmode=require
pgbouncer
から運用情報を取得するためのいくつかのコマンドを使用できます。たとえば、pgbouncer のスループットに関する情報を表示するには、show stats
を実行します。
pgbouncer=# show stats;
-[ RECORD 1 ]----+----------
database | pgbouncer
total_requests | 21138
total_received | 0
total_sent | 0
total_query_time | 0
avg_req | 0
avg_recv | 0
avg_sent | 0
avg_query | 0
コマンドの完全な一覧は、pgbouncer のドキュメントで入手できます。
ここに記載されているように、アプリケーションのログストリームで SHOW POOLS;
および SHOW STATS;
コマンドによって示されるメトリクスのサブセットも提供しています。
注意
pg:credentials と互換性がない
最近の Postgres のバグとその後の修正のために、接続プールは pg:credentials
で動作しなくなっています。
プリペアドステートメントと互換性がない
pgbouncer
を使用した接続プールや PostgreSQL への接続は、プリペアドステートメントと互換性がありません。
Heroku Connect と互換性がない
Heroku Connect では、PostgreSQL トリガーでセッション変数を使用します。これらの変数は、接続プールで使用されるトランザクションプーリングモードとは互換性がありません。
次の場合でも、Heroku Connect によって使用されるデータベースで接続プールを有効にできます。
- Heroku Connect で
SET SESSION
の代わりにSET LOCAL
をカスタムトリガーに使用する。 - マッピングの数が、データベースプランの接続制限の 25% 未満である。Heroku Connect では、マッピングごとに 1 つの直接接続を使用します。接続プールが有効なとき、直接接続のために予約されているのはデータベース接続の 25% でしかないため、マッピングが多すぎると接続の問題が発生します。
Heroku Connect によって使用されるデータベースで接続プールを有効にする場合、次のようにします。
- データベースへの直接接続を使用するように Heroku Connect を設定します。たとえば、
DATABASE_URL
とします。 - 接続プールを使用するように他のデータベース接続を設定します。たとえば、
DATABASE_CONNECTION_POOL_URL
とします。
接続制限
接続プールを使用するときは、2 つの接続制限に注意する必要があります。
クライアント接続制限
プーラーに接続したアプリは、最大 10,000 の同時接続を開くことができます。
サーバー接続制限
データベースに接続したプーラーは、データベースプランの接続制限の最大 75% を開くことができます。たとえば、データベースが standard-4 プラン (接続制限は 500) の場合、プーラーは Postgres への接続を 375 まで開くことができます。
サーバー接続の残りの 25% は、アプリからの直接接続のために予約されています。これは、Heroku Connect などの接続プールと互換性がないアプリケーションプロセスや、セッション変数を使用する必要があるその他の接続で役立ちます。
負荷
アプリケーションが高負荷の場合、PgBouncer 統計を監視することをお勧めします。PgBouncer プロセスで 15,000 ~ 20,000 トランザクション/秒を上回る状態が続くと接続キューが増加することが確認されているため、1 秒あたりのトランザクション数を監視することを特にお勧めします。
一部の変数が Ruby で想定どおりに機能しない場合がある
Postgres のセッション変数と Rails database.yml
ファイルに一覧表示されている変数が pgbouncer
で動作しない場合があります。
プーリングモード
Heroku Postgres の接続プールでは、pgbouncer のトランザクションプーリングモードを使用します。各種のプーリングモードと、それぞれの機能および注意事項についての詳細は、こちらを参照してください。
dyno での PgBouncer の実行
Heroku はクライアント側接続プールに対し、アプリケーションの dyno で pgbouncer
を実行する buildpack を提供しています。この buildpack は、複数のデータベース接続を使用する並列性の高いプロセスでの TCP のオーバーヘッドを削減するのに役立ちます。