Aurora Serverless v2の最大ACUを16から64へ引き上げても、SHOW max_connectionsの値が変わらない。パラメータグループを編集して保存しても実効値が動かない。ACUを増やせばメモリが増えるので接続数も自動で増えるはず、という想定が外れるため、設定ミスやバグを疑って切り分けに時間がかかりがちです。
これは仕様どおりの挙動です。max_connectionsはstaticパラメータで、値が確定するのはPostgreSQLのpostmaster起動時だからです。
原因はstaticパラメータとDBInstanceClassMemory
Auroraのパラメータグループでは、max_connectionsのデフォルト値が固定の数値ではなく計算式で入っています。
LEAST({DBInstanceClassMemory/9531392}, 5000)
DBInstanceClassMemoryはバイト単位のメモリ量を表す変数です。Serverless v2ではこの値が最大ACUに対応するメモリ量から算出され、現在のACUや最小ACUには連動しません。
最大ACUを変更しても、パラメータグループの値を書き換えても、DBインスタンスを再起動するまで実効値は変わりません。変更内容はpending-rebootとしてキューに積まれるだけです。PostgreSQL側から見るとpg_settings.contextがpostmasterのパラメータに該当します。プロセス配列(PGPROC)やロックのスロット数など、共有メモリの割り当て量がmax_connectionsから計算されるため、稼働中に値だけ増やすと共有メモリが不足します。もし現在のACUに連動する設計なら、スケーリングのたびに共有メモリの再割り当てが必要になり、無停止のスケーリングが成り立ちません。
再起動はクラスター単位ではなくインスタンス単位で必要です。ライターだけ再起動してもリーダーの実効値は変わらず、グローバルデータベース構成ではセカンダリリージョンのインスタンスも個別に再起動します。
未反映かどうかを確定させる3ステップ
- 対象インスタンスのエンドポイントに接続して
SHOW max_connections;を実行する。パラメータグループの表示値は判断材料になりません。 -
describe-db-instancesでParameterApplyStatusを確認する。pending-rebootであれば未反映で確定です。 -
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 <インスタンス名>
リーダーがある構成なら、リーダーを再起動してからフェイルオーバーで昇格させ、最後に旧ライターを再起動します。この順序なら書き込みの中断を切り替えの瞬間に寄せられます。アプリ側に接続リトライとコネクションプールの再接続処理が入っているかは事前に確認してください。
設定元までたどる
どこから値が来ているかを特定したい場合は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();
sourceがconfiguration fileならパラメータグループで明示指定しており、defaultなら計算式のデフォルトに任せた状態です。pending_restartがtrueなら、新しい値が設定ファイル側に届いて再起動を待っています。確認にはインスタンスエンドポイントを使ってください。クラスターエンドポイントはライターへ向くため、リーダーを見たつもりでライターを見る取り違えが起きます。
最大ACUを下げるときのほうが注意が必要
逆方向の変更のほうが障害につながりやすいです。コスト削減で最大ACUを下げても、再起動するまでmax_connectionsは大きい値のまま残ります。その後メンテナンスウィンドウのパッチ適用やフェイルオーバーで再起動がかかった時点で初めて値が縮み、接続が入りきらなくなります。ACUを下げるときは、現在の接続数ピークと新しい期待値を先に比べてください。
低ACU時のメモリ余裕も見ておきます。max_connectionsは最大ACU基準で決まる一方、実際のメモリはACUに応じて上下します。最小ACUまで縮んだ状態で最大ACU基準の接続数がフルに張られると、接続ごとのプロセスのオーバーヘッドやwork_memの確保でメモリが不足する可能性があります。
なお計算式のdivisorや1 ACUあたりのメモリ量、設定可能な上限値は、エンジンやバージョンによって異なります。作業前に公式ドキュメントとdescribe-db-parametersの出力で確認してください。
詳しくは
元記事では、describe-db-parametersとdescribe-db-cluster-parametersを使った設定値とApplyTypeの確認方法、グローバルデータベースでリージョンごとにインスタンスを棚卸しする手順、再起動したのに値が変わらない場合に疑う5つのポイントを順に解説しています。あわせてDatabaseConnectionsを実効値に対する割合で監視する考え方、ACUUtilizationやFreeableMemoryの見方、接続数を増やす前にコネクションプールやRDS Proxyを検討すべき判断基準、検証環境で同じ現象を再現する手順も載せています。