Serverless v2のmax_connections未反映

目次
  1. 結論:最大ACUを変えても、インスタンスを再起動するまでmax_connectionsは変わらない
  2. なぜ変わらないのか:DBInstanceClassMemoryとstaticパラメータの仕組み
  3. 切り分け手順:実効値・パラメータグループ・ACU・pending-rebootを順に見る
  4. 対処:再起動の進め方と、接続数を増やす以外の選択肢
  5. よくある誤解を3つ整理する
  6. よくある質問
  7. 再発防止:パラメータ変更時のチェックリストと監視項目
このテーマのまとめPostgreSQL 運用・トラブル解決ガイド|「遅い・詰まる・肥大化」を仕組みから切り分けるこのテーマのまとめRDS・Aurora 運用・トラブル解決ガイド|仕組み・障害切り分け・性能監視の全体像
本記事にはプロモーション(広告)が含まれています。

Aurora Serverless v2で最大ACUを16から64に上げてもSHOW max_connectionsの値が変わらない。パラメータグループを編集して保存しても実効値が変わらない。この相談は現場でよく受けます。ACUの上限を上げればメモリが増えるので接続数も自動で増えるはず、という想定が外れるため、設定ミスやバグを疑って調査に時間がかかりがちな箇所です。

これは仕様どおりの挙動です。max_connectionsはstaticパラメータで、値が確定するのはPostgreSQLのpostmaster起動時だからです。なぜ最大ACU側が基準になるのか、どこを見れば未反映と確定できるのか、複数インスタンスやグローバルデータベース構成でどこまで再起動が必要なのかを、内部の仕組みから整理します。

結論:最大ACUを変えても、インスタンスを再起動するまでmax_connectionsは変わらない

Aurora Serverless v2のmax_connectionsのデフォルト値は、DBインスタンスのメモリ量を表すDBInstanceClassMemoryを使った計算式で決まります。Serverless v2ではこのDBInstanceClassMemoryが、最大ACU(max capacity)に対応するメモリ量から算出されます。現在のACUは関係しません。

そしてmax_connectionsはstaticパラメータです。最大ACUを変更しても、パラメータグループの値を書き換えても、DBインスタンスを再起動するまで実効値は変わりません。変更内容は保留中(pending-reboot)としてキューに積まれるだけです。dynamicパラメータなら再起動なしで反映されますが、max_connectionsは該当しません。

さらに再起動はクラスター単位ではなくインスタンス単位で必要です。ライターだけ再起動してもリーダーの実効値は変わりません。グローバルデータベースで複数リージョンに複数インスタンスがある構成では、各インスタンスを個別に再起動します。

今すぐ確認して対処する3ステップ

障害対応中で結論だけ先に欲しい場合は、次の順で進めてください。

  1. 対象インスタンスのエンドポイントに接続してSHOW max_connections;を実行する。ここで返る値が、今そのpostmasterが持っている上限です。パラメータグループの表示値は判断材料になりません。
  2. describe-db-instancesでDBParameterGroups[].ParameterApplyStatusを見る。pending-rebootになっていれば未反映で確定です。
  3. reboot-db-instanceを実行し、起動後にもう一度SHOW max_connections;で新しい値を確認する。複数インスタンスがあるなら、リーダー→フェイルオーバー→旧ライターの順で回すと書き込み停止時間を短くできます。
# 1. 実効値
# psql -h <クラスターエンドポイント> -U <ユーザー名> -d <DB名>
# => SHOW max_connections;

# 2. 保留中かどうか
aws rds describe-db-instances \
  --db-instance-identifier <インスタンス名> \
  --query "DBInstances[].{Id:DBInstanceIdentifier,Status:DBInstanceStatus,PG:DBParameterGroups[0].DBParameterGroupName,Apply:DBParameterGroups[0].ParameterApplyStatus}" \
  --output table

# 3. 再起動
aws rds reboot-db-instance --db-instance-identifier <インスタンス名>

再起動が必要なパラメータかどうかを一瞬で見分ける方法

毎回ドキュメントを引くのは非効率なので、見分け方を2つ覚えておくと早いです。

ひとつはAWS側のApplyTypeです。describe-db-parameters(インスタンスパラメータグループ)またはdescribe-db-cluster-parameters(クラスターパラメータグループ)の出力でApplyTypeがstaticなら再起動が必要、dynamicなら不要です。

もうひとつはPostgreSQL側のcontextです。pg_settings.contextがpostmasterのパラメータは共有メモリ構造のサイズ決定に関わるため、プロセス起動時にしか確定できません。max_connectionsはまさにこれで、プロセス配列(PGPROC)、スナップショット管理用の領域、軽量ロックや通常ロックのスロット数など、共有メモリの割り当て量がこの値を使って計算されます。たとえばロックテーブルのサイズはmax_locks_per_transaction × (max_connections + max_prepared_transactions)を目安に確保されます。稼働中にmax_connectionsだけ増やすと共有メモリが不足するため、設計上、再起動なしでは変更できません。

AWSのstaticとPostgreSQLのcontext = postmasterはおおむね対応するので、どちらかを確認できれば判断は付きます。

なぜ変わらないのか:DBInstanceClassMemoryとstaticパラメータの仕組み

デフォルト値はLEAST({DBInstanceClassMemory/9531392}, 5000)で計算される

Aurora(PostgreSQL、MySQLとも)のパラメータグループでは、max_connectionsのデフォルト値が固定の数値ではなく計算式で入っています。

LEAST({DBInstanceClassMemory/9531392}, 5000)

DBInstanceClassMemoryはバイト単位のメモリ量を表す変数で、9531392はおおよそ9MiB強です。1接続あたり約9MiBを見込んでメモリ量を割り、5000で打ち止めという式になります。divisorの値はエンジンやバージョンによって異なることがあるので、実際の式は自分のパラメータグループのmax_connectionsの値で確認してください。

注意点が2つあります。

まずDBInstanceClassMemoryは、インスタンスに搭載された物理メモリ量そのものではありません。AWS側のモニタリングプロセスなどに使う分が差し引かれています。そのため「最大ACU × 2GiB ÷ 9531392」で手計算した期待値と、実機のSHOW max_connectionsがぴったり一致しないことがあります。期待値の算出は桁が合っているかの確認用と考え、最終判定はSHOW max_connectionsで行ってください。

もう一点、5000という上限はデフォルト値の計算式に含まれる上限です。パラメータとして設定できる絶対上限は別物で、後半のFAQで触れます。

Serverless v2のACUとメモリ量の関係、そして最大ACUが基準になる理由

Serverless v2ではACU(Aurora Capacity Unit)がCPUとメモリをセットで表す単位になっており、ACUが増えればメモリも比例して増えます。1 ACUあたりのメモリ量は公式ドキュメントに記載があるので、見積もりの際はそちらを参照してください。

混乱しやすいのは、ACUが負荷に応じて秒単位で上下するのにDBInstanceClassMemoryはどの時点の値なのか、という点です。答えは最大ACU基準です。

理由は前述の仕組みから逆算できます。max_connectionsは共有メモリ構造のサイズを決めるため、postmaster起動時にしか確定できません。もし現在のACUに連動してmax_connectionsが変わる設計なら、スケールアップやスケールダウンのたびに共有メモリの再割り当て、つまり実質的な再起動が必要になります。それではServerless v2の売りである無停止のシームレスなスケーリングが成り立ちません。

そこでAuroraは、起動時に最大ACUに対応するメモリ量でmax_connectionsを確定させ、その後のACU変動では値を動かしません。ACUが最小値まで縮んでいるときもmax_connectionsは最大ACU基準のままで、この点が運用上の注意点になります(後述)。

staticとdynamicの違いと、値がpending-rebootに積まれるタイミング

dynamicパラメータは、変更を保存するとAuroraがマネジメント側から該当インスタンスへ適用します。ApplyMethodにimmediateを指定すれば稼働中のインスタンスに反映されます。PostgreSQL側ではpg_reload_conf()相当の設定再読み込みで効く類です。対してstaticパラメータは、保存した時点では実効値が変わりません。インスタンスのParameterApplyStatusがpending-rebootに遷移し、次に再起動したときに適用される値として待機します。

最大ACUを変更した場合も同じです。ACU変更そのものはすぐ効いてスケーリング上限が変わりますが、連動して再計算されるmax_connectionsの新しい値は、再起動を待って初めてpostmasterに渡されます。

注意したいのは、pending-rebootがいつか勝手に適用されうる状態だという点です。メンテナンスウィンドウでのパッチ適用、証明書ローテーション、基盤ホストの異常によるフェイルオーバーなど、意図しない再起動をきっかけに保留中のパラメータが一斉に適用されることがあります。パラメータだけ先に変えておいて再起動は後で考えるという運用は、変更が想定外のタイミングで効くリスクを抱えます。意図しない再起動の調査手順はRDS証明書ローテーションで再起動される原因と対処も参考になります。

切り分け手順:実効値・パラメータグループ・ACU・pending-rebootを順に見る

「反映されない」という報告を受けたら、推測で再起動に走る前に次の4点を順に確認すると原因が一意に絞れます。

SHOW max_connectionsとpg_settingsで実効値と設定元を特定する

まず対象インスタンスに直接接続して実効値を取ります。確認にはインスタンスエンドポイントを使ってください。クラスターエンドポイントはライターに向くので、リーダーの実効値を見たつもりでライターを見ていた、という取り違えが起きます。

SHOW max_connections;

SELECT name, setting, unit, context, source, boot_val, reset_val, pending_restart
  FROM pg_settings
 WHERE name = 'max_connections';

-- 今どこに接続しているか(ライターかリーダーか)
SELECT pg_is_in_recovery(), inet_server_addr();

pg_settingsを見る意味は3つあります。contextがpostmasterであること(再起動が必要な種類だと確定できる)、boot_valとsettingの差(デフォルト計算値と現在値のどちらが効いているか)、そしてsourceがconfiguration fileかdefaultか(パラメータグループで明示指定しているのか、計算式のデフォルトに任せているのか)です。pending_restartがtrueなら、設定ファイル側に新しい値が届いていて再起動待ちだと読み取れます。

併せて、現状の接続数の余裕も確認しておきます。

SELECT count(*) AS used,
       current_setting('max_connections')::int AS max_conn,
       current_setting('max_connections')::int - count(*) AS remaining
  FROM pg_stat_activity;

Aurora PostgreSQLでは管理用に予約される接続枠が別途あるため、アプリケーションが実際に使える本数はmax_connectionsそのままにはなりません。SHOW superuser_reserved_connections;やRDS固有の予約パラメータの値も確認しておくと、上限に達していないはずなのに接続エラーになる、という二次トラブルを避けられます。

describe-db-parametersとdescribe-db-clustersで設定値とApplyTypeを確認する

次にAWS側の設定を確認します。Auroraにはクラスターパラメータグループとインスタンスパラメータグループの2系統があり、max_connectionsをどちらで設定できるかはエンジンとバージョンによって異なります。両方を調べて、どちらに値が入っているかを確定させてください。インスタンスパラメータグループ側に明示値があれば、そちらが優先されます。

# インスタンスパラメータグループ側
aws rds describe-db-parameters \
  --db-parameter-group-name <パラメータグループ名> \
  --query "Parameters[?ParameterName=='max_connections']"

# クラスターパラメータグループ側
aws rds describe-db-cluster-parameters \
  --db-cluster-parameter-group-name <クラスターパラメータグループ名> \
  --query "Parameters[?ParameterName=='max_connections']"

見るべきフィールドはParameterValue(空なら計算式のデフォルトが効く)、ApplyType、ApplyMethod、Source(userなら明示設定済み、engine-defaultなら未設定)です。

続いてACUの設定を確認します。

aws rds describe-db-clusters \
  --db-cluster-identifier <クラスター名> \
  --query "DBClusters[0].{Engine:EngineVersion,Serverless:ServerlessV2ScalingConfiguration,PG:DBClusterParameterGroup}"

MinCapacityとMaxCapacityが出力されます。取得したMaxCapacityに対応するメモリ量を計算式に当てはめ、期待値の桁がSHOW max_connectionsの値と合っているかを比べます。最大ACUを4倍にしたのに実効値が変わっていないなど桁が違うなら、未反映で確定です。

pending-rebootのインスタンスを洗い出し、どれを再起動すべきか判断する

最後に、クラスター内のどのインスタンスが保留中なのかを一覧で把握します。

aws rds describe-db-instances \
  --query "DBInstances[?DBClusterIdentifier=='<クラスター名>'].{Id:DBInstanceIdentifier,AZ:AvailabilityZone,Status:DBInstanceStatus,PG:DBParameterGroups[0].DBParameterGroupName,Apply:DBParameterGroups[0].ParameterApplyStatus}" \
  --output table

# 保留中の変更がほかにないかも確認する
aws rds describe-db-instances \
  --db-instance-identifier <インスタンス名> \
  --query "DBInstances[0].PendingModifiedValues"

ParameterApplyStatusがpending-rebootのインスタンスが再起動対象です。in-syncなのに実効値が期待と違う場合は、別の原因(後述のFAQ参照)を疑います。

PendingModifiedValuesも必ず見てください。エンジンバージョンのアップグレードなどパラメータ以外の変更が同時に保留されていると、再起動時にまとめて適用され、想定よりダウンタイムが伸びたり、確認対象が増えて切り分けが難しくなります。

この記事のテーマをさらに学べる本

PostgreSQLの内部構造やモニタリングを体系的に扱い、パラメータ変更の判断材料を広げられます。

PostgreSQL実践入門──アーキテクチャ、運用監視、性能改善
PostgreSQL実践入門──アーキテクチャ、運用監視、性能改善堀口 恭太郎/細谷 柚子/渡 佑也/山田 達朗/白石 裕輝/須賀 啓敏
楽天ブックスで詳しく見る Yahoo!ショッピングで見る

対処:再起動の進め方と、接続数を増やす以外の選択肢

フェイルオーバーを使ってダウンタイムを抑える再起動順序

リーダーインスタンスが1台以上ある構成なら、書き込み停止時間を短くする順序が使えます。

  1. リーダーを再起動する。この間の読み取りトラフィックは他のリーダー、または一時的にライターへ寄せる。再起動後にSHOW max_connections;で新しい値が入ったことを確認する。
  2. フェイルオーバーで、再起動済みのリーダーをライターに昇格させる。書き込みの中断はこの切り替えの瞬間だけになる。
  3. 旧ライター(新リーダー)を再起動する。これで全インスタンスの実効値が揃う。
# 2. 再起動済みリーダーへ明示的にフェイルオーバー
aws rds failover-db-cluster \
  --db-cluster-identifier <クラスター名> \
  --target-db-instance-identifier <昇格させるリーダー名>

ライターを単純にreboot-db-instanceすると、その再起動中は書き込みができません。フェイルオーバーを挟む方式でも切り替えの瞬間に接続は切れますが、断続時間を再起動時間から切り替え時間に置き換えられます。

ただしフェイルオーバー後は、昇格したインスタンスのバッファキャッシュが温まっていないために一時的に性能が落ちることがあります。Cluster Cache Managementを含めた切り替え前後の実務的な注意点はAuroraインスタンスクラス変更のダウンタイム最小化手順で整理しているので、同じ考え方が使えます。また、アプリ側に接続リトライとコネクションプールの再接続処理が入っているかを事前に確認してください。これが無いと、切り替え自体は数十秒で終わってもアプリが復帰しません。

グローバルデータベース・複数リージョン構成では各インスタンスを個別に再起動する

Aurora Global Databaseで複数リージョンに複数インスタンスを配置している構成では、セカンダリリージョンのインスタンスも個別に再起動が必要です。プライマリクラスターのライターを再起動しても、セカンダリリージョンのヘッドインスタンスやそのリーダーのmax_connectionsは変わりません。

作業はインスタンスの棚卸しから始めます。リージョンごとに--regionを切り替えてdescribe-db-instancesを回し、対象一覧とそれぞれのParameterApplyStatusを表にしてください。パラメータグループはリージョンリソースなので、プライマリ側だけ値を変更してセカンダリ側のグループを変更し忘れる抜けが起きやすく、再起動しても値が変わらない原因の定番です。セカンダリ側の再起動は、フェイルオーバー訓練とは別に計画します。昇格させる予定のインスタンスが古いmax_connectionsのままだと、災害時の切り替え後に接続数が足りなくなります。

# リージョンごとに棚卸しする
for r in <リージョン1> <リージョン2>; do
  echo "== $r =="
  aws rds describe-db-instances --region "$r" \
    --query "DBInstances[].{Id:DBInstanceIdentifier,Apply:DBParameterGroups[0].ParameterApplyStatus}" \
    --output table
done

max_connectionsを手動で固定する場合に最小ACUのメモリと整合させる注意点

デフォルトの計算式をやめて固定値を入れるケースもありますが、Serverless v2では固有の注意点があります。

max_connectionsは最大ACU基準で決まる一方、実際のメモリはACUに応じて上下します。アイドル時に最小ACUまで縮んだ状態で最大ACU基準の接続数がフルに張られると、メモリが不足する可能性があります。PostgreSQLは接続ごとにOSプロセスを起こすアーキテクチャなので、接続1本あたりにプロセスのオーバーヘッドとwork_mem、temp_buffersなどが乗ります。work_memはソートやハッシュのたびに確保され、1クエリ内で複数回確保されることもあります。接続数を大きく取るほど、低ACU時のメモリ余裕が減ります。

実務上は、まず常時張られる接続数の見込み(アプリのプール最大値 × アプリインスタンス数 × 冗長分)を出します。その本数が最小ACUのメモリでも成立するかを確認し、成立しないならmax_connectionsを上げる前に最小ACUを引き上げる方が安全です。最小ACUを絞りすぎると、接続数だけでなくバッファキャッシュのヒット率にも影響します。固定値を入れるなら、work_memなどセッション単位でメモリを消費するパラメータも併せて見直してください。max_connectionsだけ増やしてwork_memが大きいままだと、同時実行が増えたときにメモリ圧迫でOOMやスワップ相当の状況に陥ります。

接続数を増やす前にプーリングやRDS Proxyを検討すべきケース

max_connectionsを増やすより接続の作り方を見直した方が効果的な場面も多いです。Lambdaやコンテナのオートスケールでインスタンス数に比例してDB接続が増える、pg_stat_activityにidleのセッションが大量に居座っている(アプリ側のプールが大きすぎる)、短時間に接続と切断を繰り返している、といった特徴があるときです。PostgreSQLは接続ごとにプロセスをforkするため、接続確立のコストが相対的に重く、CPUを無駄に使います。

対策の候補は、アプリ側のコネクションプール、PgBouncerなどのプーラー、RDS Proxyです。プール最大値はDBの実効上限から逆算して設計します。RDS Proxyは接続を多重化してDB側のセッション数を抑えられるほか、フェイルオーバー時の接続維持にも役立ちます。ただしトランザクションやセッション状態によってはピン留め(pinning)が発生して多重化の効果が落ちるため、アプリの使い方との相性を検証した上で採用してください。Serverless v2やエンジンバージョンごとの対応状況はリージョンによって差があり得るので、最新の対応範囲は公式ドキュメントで確認してください。

この記事のテーマをさらに学べる本

EC2・IAM・RDSなどAWSの運用手法を基本から解説しており、再起動を伴う運用作業の整理に役立ちます。

AWS運用入門
AWS運用入門佐竹 陽一/山崎 翔平/小倉 大/峯 侑資
楽天ブックスで詳しく見る Yahoo!ショッピングで見る

よくある誤解を3つ整理する

「Serverless v2ならパラメータも全部自動で調整される」

Serverless v2が自動で行うのは、ACUの範囲内でのコンピュートとメモリのスケーリングです。パラメータグループの値、とくにstaticパラメータの反映は自動ではありません。

容量は自動、設定は手動と切り分けると分かりやすいです。shared_buffersのようにAurora側がACUに応じて調整する領域と、max_connectionsのように起動時に固定される領域があり、後者は明示的な再起動が必要です。サーバーレスでも運用はゼロになりません。容量計画の手間が減る代わりに、ACUレンジとパラメータの整合性という確認項目が増える、というのが実態に近いです。

「最大ACUを上げればmax_connectionsも自動で上がる」

これが最も多い誤解です。最大ACUの変更はスケーリング上限の変更で、その時点で効くのはどこまで伸びられるかだけです。max_connectionsの再計算結果がpostmasterに渡るのは次回起動時になります。

逆方向も同じです。最大ACUを下げた場合、再起動するまでmax_connectionsは大きい値のまま残ります。コスト削減のために最大ACUを下げたあと、メンテナンスウィンドウなどの再起動で初めてmax_connectionsが縮み、接続数が入りきらなくなって障害化する、という順序が成立します。ACUを下げるときこそ、現在の接続数ピークと新しい期待値を先に比べてください。

「クラスターパラメータグループに書けば全インスタンスへ即反映される」

クラスターパラメータグループはクラスター配下のインスタンスに共通の設定を配る仕組みですが、配ることと反映されることは別です。staticパラメータであれば、各インスタンスでの再起動が必要です。クラスター単位の操作でインスタンスのpostmasterが再起動するわけではありません。

加えて、インスタンスパラメータグループ側に同じパラメータの明示値があると、そちらが優先されます。クラスター側を直したのに効かないときは、インスタンス側のグループに古い値が残っていないかをdescribe-db-parametersで確認してください。グローバルデータベースのように複数リージョンへまたがる構成では、リージョンごとにパラメータグループが別物であることも併せて意識します。

よくある質問

max_connectionsは最小ACUと最大ACUのどちらで決まる?

最大ACUです。Serverless v2では最大ACUに対応するメモリ量を前提にDBInstanceClassMemoryが決まり、そこから計算式でmax_connectionsが導かれます。現在のACUや最小ACUには連動しません。

この非対称性が運用上のリスクになります。最小ACUまで縮んでいるときも接続上限は最大ACU基準のままなので、低負荷時に大量の接続が張られるとメモリ面で苦しくなります。最小ACUは、アイドル時のコストに加えて最悪ケースで同時接続を支えられるかという観点でも決めてください。

再起動なしでmax_connectionsを反映させる方法はある?

ありません。max_connectionsはPostgreSQLのcontext = postmasterに属し、共有メモリ構造のサイズ決定に使われるため、プロセス起動時にしか確定できません。AWS側でApplyMethodにimmediateを指定しても、staticパラメータはpending-rebootに積まれるだけです。

できるのはダウンタイムを短くすることです。リーダーを先に再起動してフェイルオーバーで昇格させる手順を使えば、書き込みの中断を切り替えの瞬間に寄せられます。どうしても再起動できないなら、プール設定の見直し、RDS Proxy、アイドル接続の整理で接続数そのものを減らす方向に切り替えるのが現実的です。

max_connectionsは5000より大きい値に設定できる?

計算式に含まれる5000は、デフォルト値の上限です。パラメータとして明示的な値を指定できますし、エンジンが許す上限は別に定義されています。許容範囲はdescribe-db-parameters出力のAllowedValuesで確認できます。

ただし設定できることと性能が出ることは別問題です。PostgreSQLは接続ごとにプロセスを起こすため、接続数が増えるほどコンテキストスイッチ、スナップショット取得時のプロセス配列走査、ロック管理のコストが増えます。接続数を数千本規模にするなら、プーラーを前段に置いてDB側のセッション数を抑える設計の方が、スループットも安定性も良くなるのが一般的です。明示値を入れる前に、AllowedValuesと実際のメモリ余裕の両方を確認してください。

再起動したのに値が変わらないときは何を疑えばいい?

次の順で確認します。

  1. 再起動したインスタンスと、値を確認したインスタンスが一致しているか。クラスターエンドポイント経由で確認していると、再起動したリーダーではなくライターを見ている可能性があります。pg_is_in_recovery()やインスタンスエンドポイントで接続先を確定させてください。
  2. 編集したパラメータグループが、そのインスタンスに実際に割り当てられているか。describe-db-instancesのDBParameterGroups[].DBParameterGroupNameと、編集したグループ名を突き合わせます。新しいグループを作ったが割り当てていない、という取り違えは定番です。
  3. インスタンスパラメータグループ側に明示値が残っていないか。クラスター側を直してもインスタンス側が優先されます。
  4. 期待値の計算が合っているか。DBInstanceClassMemoryは物理メモリから管理用の分を差し引いた値です。期待値とわずかにずれる程度なら、正常に反映されていると判断できます。
  5. 別リージョンのインスタンスを見ていないか。グローバルデータベース構成では、CLIの--regionの指定ミスで別クラスターを調べていることがあります。

再発防止:パラメータ変更時のチェックリストと監視項目

ACU変更・インスタンスクラス変更時に実効値を再確認する運用手順

この手の問題は、仕組みを知らなかったことよりも手順書に書かれていなかったことで再発します。最大ACUの変更やインスタンスクラスの変更を行う手順には、次の項目を明記してください。

  • 変更前にSHOW max_connections;の値と、ピーク時の接続数(pg_stat_activityの件数)を記録する。
  • 変更後にdescribe-db-instancesでParameterApplyStatusを確認し、pending-rebootのインスタンスを一覧化する。
  • 再起動対象のインスタンスをすべて列挙する(リーダー、別リージョンのヘッドインスタンスとそのリーダーを含む)。
  • 再起動後、各インスタンスのエンドポイントに個別に接続してSHOW max_connections;を確認する。クラスターエンドポイントだけの確認で済ませない。
  • 新しいmax_connectionsが、アプリ側のプール最大値の合計を上回っていることを確認する。

staticパラメータの反映には再起動が必要、という一文をチェックリストに入れておくだけで、同じ問い合わせはかなり減ります。RDS/Aurora全体の運用観点でのチェックポイントはRDS・Aurora運用・トラブル解決ガイドにまとめているので、手順書を作るときに参照してください。

接続数の上限に近づいていることを事前に検知する監視の置き方

max_connectionsの問題は、たいてい「接続できなくなった」という形で表に出ます。先に気づくための監視を置いておきます。

  • CloudWatchのDatabaseConnectionsにアラームを設定する。閾値は固定値ではなくmax_connectionsの実効値に対する割合で決める。実効値が変わったらアラーム閾値も見直す、という対応関係を手順書に書いておく。
  • ServerlessDatabaseCapacityとACUUtilizationを併せて見る。接続数が多いのにACUが最小付近で張り付いている時間帯は、低ACU時のメモリ圧迫リスクが高い。
  • FreeableMemoryを接続数と重ねて見る。接続数の増加に対してメモリが線形に減っていくなら、接続あたりのメモリ消費が大きい(work_memが過大など)サイン。
  • pg_stat_activityのstate別件数を定期取得し、アイドル接続を可視化する。接続数は上限近くだが実際に働いているのは一部、というケースを検出できる。この場合の対応はプール設定の見直しです。
  • リーダーを使った構成なら、再起動やフェイルオーバーの前後でレプリケーション遅延も見る。確認の勘所はAuroraレプリカラグ監視|AuroraReplicaLagにまとめています。

検証環境で同じ現象を再現して手順を確かめる

本番で初めて再起動手順を試すのは避けたいところです。この現象は検証環境で簡単に再現できるので、手順の確認を兼ねて一度通しておくことを勧めます。

  1. Aurora Serverless v2のクラスターを作成する(できればリーダーも1台用意し、フェイルオーバー手順まで試せる構成にする)。
  2. SHOW max_connections;の値を記録する。併せてpg_settingsのcontext、source、boot_valも控える。
  3. 最大ACUを変更する。この時点でdescribe-db-instancesのParameterApplyStatusがpending-rebootに遷移することを確認する。
  4. 再起動せずにSHOW max_connections;を実行し、値が変わっていないことを確かめる。
  5. リーダーを再起動→フェイルオーバー→旧ライターを再起動の順で回し、各インスタンスのエンドポイントでSHOW max_connections;が新しい値になることを確認する。
  6. 切り替えの前後でアプリ(または簡易な接続スクリプト)がどう振る舞うかを観察し、リトライ処理の有無を確認する。

この一連の値と所要時間を自分の環境で記録しておくと、本番作業時の見積もりと関係者への説明が楽になります。所要時間のような環境依存の数値は他人の記事の値を流用せず、必ず自分の構成で計測してください。

なおmax_connectionsの計算式に使われるdivisor、1 ACUあたりのメモリ量、設定可能な上限値、RDS Proxyの対応範囲などは、エンジンやバージョン、リージョンによって異なり、将来変更される可能性もあります。作業前には、AWSの公式ドキュメントと自分の環境のdescribe-db-parameters出力で最新の値を確認してください。

OSS-DB Silver 対策テキスト(OSS教科書)

PostgreSQLの仕組みを体系的に学ぶなら、OSS-DB Silverの公式対応テキストが近道です。資格を取らなくても基礎固めに役立ちます。

OSS教科書 OSS-DB Silver Ver.3.0対応 (EXAMPRESS) [ 福岡 博 ]

OSS教科書 OSS-DB Silver Ver.3.0対応 (EXAMPRESS) [ 福岡 博 ]