0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Aurora Serverless v2でmax_connectionsが変わらない理由

0
Posted at

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ステップ

  1. 対象インスタンスのエンドポイントに接続してSHOW max_connections;を実行する。パラメータグループの表示値は判断材料になりません。
  2. describe-db-instancesで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 <インスタンス名>

リーダーがある構成なら、リーダーを再起動してからフェイルオーバーで昇格させ、最後に旧ライターを再起動します。この順序なら書き込みの中断を切り替えの瞬間に寄せられます。アプリ側に接続リトライとコネクションプールの再接続処理が入っているかは事前に確認してください。

設定元までたどる

どこから値が来ているかを特定したい場合は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を検討すべき判断基準、検証環境で同じ現象を再現する手順も載せています。

Aurora Serverless v2でmax_connectionsが反映されない原因と対処

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?