導入・背景
今回は自分が対応した案件においてAurora Global Databaseを採用する機会があったので、実際に採用するにあたって考慮が必要だったこと・注意しないといけないことを備忘も兼ねて残していこうと思います。本記事は2回に分けて記載予定で、1本目では主に理論の部分でAurora Global Databaseの仕様を単一リージョンのAuroraとの違いという観点で整理します。2本目では、実際に東京・大阪間でGlobal DBを構築して、スイッチオーバーとフェイルオーバーの挙動を検証する予定です。
案件でGlobal DBを選んだ理由は、ざっくり以下の3点です。
| 要件・方針 | 内容 |
|---|---|
| マルチリージョンのホットスタンバイ | リージョン障害時にも短時間で切り替えられる構成が求められていた |
| RPO約1分 | バックアップからのリストアでは到底満たせない、厳しめのRPO要件があった |
| 運用負荷の軽減 | 今後の運用を考えたときに、DBが運用上の急所になるのは避けたかったのとパッチ対応を減らすためにもマネージドサービスに寄せて運用を楽にしたかった |
特に2点目のRPOが大きくて、日次バックアップ+クロスリージョンコピーのような構成では1分という要件は満たせません。かといって、DBエンジンのレプリケーションを自前で組んで面倒を見るのは、運用フェーズのことを考えるとあまりやりたくない...というところで、ストレージ層でレプリケーションしてくれるAurora Global DBに落ち着きました。
なお、本記事の内容は案件の内容を参考にしているため一部内容をぼかしております。ご容赦いただけますと幸いです。
また、本記事は2026年10月時点の公式ドキュメントをもとに記載しています。エンジンはPostgreSQLを前提としMySQLとの差分は必要な箇所のみ触れます。
想定読者
- AWSの基本的なサービスを理解しているインフラエンジニア
- マルチリージョンのDR構成を検討している方
- 「Global DBにすればDRは大丈夫」となんとなく思っているけど、実態はよくわからない方
- ヘッドレス構成の存在を知らない方
※ Auroraのクラスター・インスタンス・エンドポイントなどの基本的な概念は理解している前提で進めます。
この記事でわかること
- Aurora Global Databaseの構成と、DR方式の中での位置づけ
- ストレージ層レプリケーションの仕組みと、durability lag/RPO lagの違い
- 構成上の要件と、Global DBで使えなくなる機能
- グローバルライターエンドポイントと書き込み転送の注意点
- スイッチオーバーとフェイルオーバーの違い
-
rds.global_db_rpoによるRPOの制御 - 単一リージョンのAuroraから運用が変わるポイント
1. Aurora Global Databaseとは
1.1 構成の概要
Aurora Global Databaseは、複数のAWSリージョンにまたがるAuroraクラスターの集合です。
- プライマリクラスター: メインで業務処理を行う1つのリージョンに存在する書き込みを受け付ける唯一のクラスター
- セカンダリクラスター: 最大10リージョンに作成可能な読み取り専用のクラスター
プライマリへの書き込みは専用のインフラを通じてセカンダリリージョンへ複製されます。公式ドキュメントでは、このレプリケーションの遅延は通常1秒未満とされています。(下記画像は公式ドキュメントより引用)
セカンダリリージョンの数は2025年5月に最大10まで拡張されています。
1.2 ヘッドレス構成について
Global DBのセカンダリクラスターは、読み取り用のDBインスタンス(Reader)を置いて使うのが一般的です。ただ、実はDBインスタンスを1台も置かない構成を取ることもできます。これをヘッドレス構成と呼びます。
| 構成 | セカンダリにあるもの | セカンダリでの読み取り |
|---|---|---|
| インスタンスあり | ストレージボリューム + Readerインスタンス | できる |
| ヘッドレス | ストレージボリュームのみ | できない |
DBインスタンスがないのにデータが複製されるの?と思われるかもしれませんが、ヘッドレス構成でもセカンダリのストレージボリュームはプライマリと同期され続けます。というのも、AuroraはDBインスタンス(コンピュート)とクラスターボリューム(ストレージ)が分離されていてGlobal DBのレプリケーションはストレージ側で行われているためです。
読み取りが不要でDRのためだけにセカンダリを持っておきたいケースでは、インスタンス料金を払わずにデータだけ別リージョンに置いておくという選択を取ることも可能です。(どの程度のDR要件が求められるかにもよりますが、費用面的にはスナップショットからのリストアの方がお安いのですが...)
1.3 DR方式の中での位置づけ
前回のDR記事では4つのDR方式を整理しましたが、ここではAuroraの復旧手段ごとにRTO・RPOの目安を整理すると以下のようになります。
| 復旧手段 | RTOの目安 | RPOの目安 | 備考 |
|---|---|---|---|
| 別リージョンにコピーしたスナップショットからの復元 | 数時間 | スナップショットの取得・コピーの間隔に依存 | クラスター単位での再作成が必要 |
| PITR | — | 直近5分以内 | 同一リージョン内の復旧手段。リージョン障害には使えない |
| Global DB(スイッチオーバー) | 対象バージョンでは通常30秒未満 | 0 | 計画停止など事前に計画された切り替え用 |
| Global DB(フェイルオーバー) | 数分程度 | 秒単位(レプリケーションラグに依存) | 障害時の切り替え用 |
スナップショットからの復元のRTOはデータ量などによって大きく変わるため、あくまで目安として記載しています。それ以外の数字は公式ドキュメントの記載より引用となります。また、Global DBの実際の切り替え時間は2本目で計測します。
2. レプリケーションの仕組み
2.1 ストレージ層での複製について
通常のPostgreSQLのレプリケーションは、WAL(先行書き込みログ)をDBエンジン同士でやり取りするストリーミングレプリケーションです。
一方、Aurora Global DatabaseはDBエンジンではなくクラスターのストレージボリュームを使って複製します。公式ドキュメントではこの方式によりプライマリへの性能影響が小さく、DBインスタンスのリソースをアプリケーションの読み書きに使えるとされています。
| 観点 | PostgreSQLのストリーミングレプリケーション | Aurora Global Database |
|---|---|---|
| 複製する層 | DBエンジン(WAL送信) | ストレージ層 |
| 複製先 | スタンバイサーバー | セカンダリリージョンのストレージボリューム |
| 複製の担い手 | DBエンジン(WAL送信プロセス) | ストレージ層の専用インフラ。プライマリへの性能影響は小さい |
| セカンダリの読み取り | スタンバイサーバーで読む | セカンダリクラスターのReaderインスタンスで読む |
大きなポイントとしてはセカンダリリージョンにはストレージボリュームが丸ごと存在するという点です。
通常のPostgreSQLではプライマリのDBプロセスがWALを送り、スタンバイ側のDBプロセスがそれを受け取って適用します。そのため受け取る側にもDBサーバーが必要です。一方、Global DBではプライマリのストレージボリュームからセカンダリのストレージボリュームへ直接複製されるため、セカンダリ側にDBサーバーが存在する必要はありません。
セカンダリのReaderインスタンスは同期されたボリュームを読みに行くだけの存在です。この部分は単一リージョンのAuroraでReaderが同じクラスターボリュームを読みに行くのと同じ構図ですね。
公式ドキュメントでもヘッドレス構成について以下のように明記されています。
Even without any DB instance in the secondary cluster, Aurora keeps the storage volume in sync with the primary Aurora DB cluster.
(セカンダリクラスターにDBインスタンスが1台もなくても、Auroraはストレージボリュームをプライマリと同期した状態に保ちます)
1.2で触れたヘッドレス構成が成り立つのはこの仕組みのおかげです。
2.2 durability lagとRPO lagの違い
Global DBの「ラグ」には2種類あります。ここは割と混同しやすいところです。
Aurora PostgreSQLではプライマリクラスターでaurora_global_db_status()関数を実行すると、セカンダリごとのラグを確認できます。
SELECT * FROM aurora_global_db_status();
以下は公式ドキュメントに掲載されている出力例です。実機での出力は2本目で東京・大阪の環境を構築した際に載せる予定です。
aws_region | highest_lsn_written | durability_lag_in_msec | rpo_lag_in_msec | last_lag_calculation_time | feedback_epoch | feedback_xmin
------------+---------------------+------------------------+-----------------+----------------------------+----------------+---------------
us-east-1 | 93763984222 | -1 | -1 | 1970-01-01 00:00:00+00 | 0 | 0
us-west-2 | 93763984222 | 900 | 1090 | 2020-05-12 22:49:14.328+00 | 2 | 3315479243
| 項目 | 意味 |
|---|---|
| durability_lag_in_msec | プライマリとセカンダリで、ストレージに書き込まれた最新のLSN(ログシーケンス番号)の時刻差 |
| rpo_lag_in_msec | プライマリとセカンダリで、最新のユーザートランザクションのコミットの時刻差 |
違いがわかりやすいのが、公式ドキュメントに載っている長時間トランザクションの例です。
BEGIN;
INSERT INTO table1 SELECT ...; -- 1時間かかる大量INSERT
COMMIT;
BEGINの直後にプライマリとセカンダリの間のネットワークが切れた場合、以下のように値が推移します。
| タイミング | durability lag | RPO lag |
|---|---|---|
| INSERT実行中 | 増え続ける | 0のまま |
| INSERT完了時(コミット前) | 約1時間 | 0のまま |
| コミット後 | — | 増え始める |
コミットされていないデータは、そもそもフェイルオーバーで失われても困らないデータです。そのため、「この瞬間にフェイルオーバーしたら、コミット済みのデータがどれくらい失われるか」を表すのはRPO lagの方ということになります。
CloudWatchではAuroraGlobalDBRPOLagメトリクス(ミリ秒)で確認できます。Aurora PostgreSQLは全バージョンでこのメトリクスが使えます。Aurora MySQLは3.04.0以降/2.12.0以降で使え、それより前のバージョンではAuroraGlobalDBReplicationLagを見ることになります。
注意点として、ラグ系のメトリクスはセカンダリリージョン側にしか存在しません。スイッチオーバーやフェイルオーバーでプライマリとセカンダリが入れ替わると、メトリクスを見るリージョンも変わります。アラームやダッシュボードを作り直す必要が出てくるので、監視設計の段階で意識しておきたいところです。
3. 構成の要件と制約
3.1 構成の上限
| 項目 | プライマリリージョン | セカンダリリージョン |
|---|---|---|
| Auroraクラスター数 | 1 | 最大10 |
| Writerインスタンス | 1 | 0 |
| 読み取り専用インスタンス(クラスターあたり) | 最大15 | 最大16 |
セカンダリクラスターは読み取り専用なので、通常の上限である15台より1台多い16台までReaderを置けます。
また公式ドキュメントの表では、プライマリクラスターの読み取り専用インスタンスの上限は「15 − セカンダリリージョン数」と記載されています。セカンダリリージョンを増やすほどプライマリ側に置けるReaderが減るのでセカンダリを多数置く構成では注意が必要です。
そのほか以下の要件があります。
- 各リージョンのクラスター名は、全リージョンを通して一意である必要がある
- 同じリージョンに2つのクラスターを置くことはできない
特に1点目は意外と盲点だったりするので、クラスター名の最後にリージョン識別子(-tkyとか-oskなど)をつけることによって回避したほうがよさそうですね。
3.2 インスタンスクラス
Global DBのインスタンスクラスは、公式ドキュメントでメモリ最適化系のインスタンスクラスであることが必須とされていて、そのうえでdb.r5以上が推奨されています。
検証環境でよく使うdb.t系はバースト可能なインスタンスクラスでメモリ最適化系には含まれないので、実際にどうなるのか試してみました。db.t3.mediumのWriterインスタンスを持つクラスターに対して、「アクション」から「AWSリージョンを追加」を選択します。
すると、以下のダイアログが表示されてリージョンを追加できませんでした。
このクラスターの1つ以上のDBインスタンスには、Auroraグローバルデータベースと互換性がないサイズがあります。このクラスターにAWSリージョンを追加するには、まず小さすぎるインスタンスを変更して、互換性のあるサイズにしてください。
db.t系はメモリ最適化系ではないため必須要件を満たせず、Global DBを構成できないということですね。検証環境のようにコストを抑えたい場合でも、Global DBではdb.r系などのメモリ最適化クラスを選ぶ必要があります。
既存のクラスターを後からGlobal DBにしようとしている場合は、先にインスタンスクラスの変更が必要になります。インスタンスクラスの変更はインスタンスの再起動を伴うので、検証環境をdb.t系で作っていると、Global DB化の前にひと手間かかることになります。Aurora Serverless v2を使う場合は、プライマリリージョンのクラスターの最小容量を8 ACU以上にすることが推奨されています。Serverless v2の最小容量は0や0.5 ACUまで下げられますが、Global DBではそこまで絞らないようにという位置づけです。
3.3 ヘッドレス構成
セカンダリクラスターにはDBインスタンスを1台も置かないヘッドレス構成を取ることができます。2.1で触れたとおりレプリケーションはストレージ層で行われるため、インスタンスがなくてもデータの複製は続きます。
| 構成 | セカンダリでの読み取り | 切り替え前の作業 | コスト |
|---|---|---|---|
| インスタンスあり | できる | 不要 | インスタンス料金がかかる |
| ヘッドレス | できない | DBインスタンスの追加が必要 | ストレージとレプリケーションの料金のみ |
ヘッドレス構成でスイッチオーバー/フェイルオーバーをする場合は、事前にセカンダリへDBインスタンスを追加する必要があると公式ドキュメントに明記されています。インスタンスの作成時間がそのままRTOに上乗せされます。
ヘッドレス構成にしているクラスターに対して実際にdb.r5.largeのインスタンスを追加した際の時間を測定してみました。
インスタンスの追加は、通常のクラスターにReaderを追加するときと同じcreate-db-instanceコマンドで行います。--regionにはプライマリではなく、セカンダリクラスターのリージョンを指定します。
aws rds create-db-instance \
--region <セカンダリのリージョン> \
--db-instance-identifier <追加するインスタンス名> \
--db-cluster-identifier <セカンダリクラスター名> \
--engine aurora-postgresql \
--db-instance-class db.r5.large
--db-instance-classには、3.2で触れたとおりメモリ最適化クラス(推奨はdb.r5以上)を指定する必要があります。また、--db-parameter-group-nameを指定しない場合はデフォルトのDBパラメータグループが割り当てられるので、カスタムのパラメータグループを使う場合は合わせて指定しておきます。
インスタンスの状態は以下のコマンドで確認できます。availableになれば、スイッチオーバー/フェイルオーバーの切り替え先として使える状態です。
aws rds describe-db-instances \
--region <セカンダリのリージョン> \
--db-instance-identifier <追加するインスタンス名> \
--query 'DBInstances[].DBInstanceStatus' \
--output text
実際にインスタンスが0台のクラスターに対してコマンドを実行した画面が以下です。
なお、上記の画面はGlobal DBのセカンダリではなく、単一のリージョン別クラスターに対して実行したものです。インスタンスが0台のクラスターにインスタンスを追加するという操作自体は同じですが、以下の点が異なります。
- 単一のクラスターでは、最初に追加したインスタンスがWriterになる(セカンダリに追加した場合はReaderのまま)
- セカンダリでは、プライマリからレプリケーションされているボリュームにインスタンスを接続する
インスタンスが利用可能になった時点の画面が以下です。単一のクラスターなので、追加したインスタンスのロールがライターインスタンスになっていることがわかります。
コマンドの実行(14:27頃)から利用可能になったことを確認するまで(14:34頃)、約6分でした。スクリーンショットを撮ったタイミングでの計測なので、実際にはもう少し早く利用可能になっていた可能性があります。
そのため、所要時間はあくまで参考値として見ていただければと思います。ただ、ヘッドレス構成で切り替える場合は、少なくとも数分単位のインスタンス作成時間がRTOに上乗せされると考えておいたほうがよさそうです。
3.4 Global DBで使えない・制約がある機能
単一リージョンのAuroraでは当たり前に使えていた機能のうち、Global DBでは使えない、または制約があるものを整理します。
| 機能 | Global DBでの扱い |
|---|---|
| バックトラック(Aurora MySQL) | 非対応 |
| セカンダリクラスターのAurora Auto Scaling | 非対応 |
| クラスターの停止・起動 | 個別のクラスターでは不可 |
| 自動マイナーバージョンアップグレード | 設定はできるが効果なし |
| Secrets Managerによるマスターユーザーパスワード管理 | 非対応。リージョン追加前に統合を無効にする必要がある |
| クラスターの名前変更 | Global DBのメンバーである間は不可(グローバルクラスター識別子とインスタンス識別子は変更可) |
| クラスターキャッシュ管理(Aurora PostgreSQL) | セカンダリクラスターでは非対応 |
この中で特に影響が大きいのは、以下の2つかなと思います。
①クラスターを停止できない
検証環境や夜間停止で使っていた「使わないときは止めておく」運用がそのままでは使えません。2リージョン分のインスタンス料金が常にかかり続けます。
②Secrets Managerとの統合が使えない
マスターユーザーのパスワードをRDSとSecrets Managerの統合で管理している場合、そのクラスターをGlobal DBのプライマリにするにはまず統合を無効にする必要があります。認証情報の管理方法を別途考える必要があります。(Secrets Managerでのパスワード管理ができないわけではありません。)
4. エンドポイントと接続の設計
4.1 エンドポイントの種類
Global DBでは、単一リージョンのAuroraにはないグローバルライターエンドポイントが追加されます。
| エンドポイント | 向き先 | 切り替え後の挙動 |
|---|---|---|
| グローバルライターエンドポイント | その時点のプライマリクラスターのWriter | 自動で新しいプライマリを向く |
| クラスターエンドポイント(プライマリ) | プライマリクラスターのWriter | 切り替え後は読み取り専用になる |
| クラスターエンドポイント(セカンダリ) | セカンダリクラスター。コンソール上はinactiveと表示 |
昇格後は書き込み可能になる |
| リーダーエンドポイント | 各クラスターのReader | 変わらない |
グローバルライターエンドポイントは以下の形式です。先頭にグローバルクラスター識別子が入るため、Global DBの名前を変えるとエンドポイント名も変わります。
<グローバルクラスター識別子>.global-<一意の文字列>.global.rds.amazonaws.com
4.2 エンドポイントを変えなくていいと実際につながるかは別問題
グローバルライターエンドポイントを使えば切り替え後にアプリケーションの接続先を書き換える必要はありません。ただ、これで切り替えが完結するわけではない点に注意が必要です。
①ネットワークは自分で用意する必要がある
グローバルライターエンドポイントが大阪のクラスターを向いても、東京のVPCにいるアプリケーションから大阪のVPCに届かなければ接続できません。公式ドキュメントでも、アプリケーションとプライマリ・セカンダリ両方のリージョンのVPCの間で接続を用意しておくよう案内されています。(具体的な方法としては、VPCピアリングやAWS Transit Gatewayなどが選択肢になります)
これはアプリケーションを東京に残したままDBだけ大阪に切り替えるケースの話です。アプリケーションごと大阪に切り替えるのであれば不要ですが、どちらのパターンでDRするのかは設計段階で決めておく必要があります。
②DNSキャッシュの分だけ切り替えが遅れる
グローバルライターエンドポイントの切り替えはDNSで行われます。アプリケーションやOS、ネットワーク機器がDNSの結果をキャッシュしているとその分だけ古いプライマリを向き続けます。
公式ドキュメントでは、DNSキャッシュのTTLを5秒程度の低い値にすることが推奨されています。また、Aurora側がグローバルライターエンドポイントのDNS変更を検知するとRDSイベントが発行されるので、そのイベントを基準にアプリケーションの書き込みを再開するという方法も示されています。
③フェイルオーバー時のスプリットブレイン
フェイルオーバー時、Auroraは旧プライマリへの書き込みを止めようとします(書き込みフェンシング)。ただし、これはベストエフォートであり、旧プライマリが一時的に書き込みを受け付けてしまう可能性があると公式ドキュメントに明記されています。
グローバルライターエンドポイント経由の書き込みにはデータロスを抑えるための追加の保護があるとされていますが、旧プライマリのクラスターエンドポイントを直接参照しているアプリケーションがあるとこのリスクが高まります。そのため、接続先は全てグローバルライターエンドポイントに寄せておくのが基本方針になるかなと思います。
4.3 書き込み転送
セカンダリリージョンのアプリケーションから、たまに書き込みが発生するケース向けに書き込み転送という機能があります。セカンダリクラスターのリーダーエンドポイントに書き込みを送ると、Auroraがプライマリへ転送してくれます。
Aurora PostgreSQLでの対応バージョンは以下のとおりです。
| メジャーバージョン | 対応マイナーバージョン |
|---|---|
| 16以降 | 全マイナーバージョン |
| 15 | 15.4以降 |
| 14 | 14.9以降 |
デフォルトでは無効でセカンダリクラスターごとに有効化します。有効化・無効化にダウンタイムや再起動は伴いません。
ただし、転送できるSQLには制限があります。
| 転送できる | 転送できない |
|---|---|
| INSERT, UPDATE, DELETE | DDL |
| SELECT FOR UPDATEなど | ANALYZE, VACUUM, CLUSTER |
| PREPARE, EXECUTE | COPY, TRUNCATE, LOCK |
| 上記のEXPLAIN | SAVEPOINT, SELECT INTO, カーソル |
| — | GRANT, REVOKEなど |
また、ユーザー定義の関数・プロシージャは非対応で分離レベルはSERIALIZABLEが使えません。
読み取りの一貫性はapg_write_forward.consistency_modeパラメータで制御します。
| 設定値 | 挙動 |
|---|---|
| SESSION(デフォルト) | 同じセッションで転送した書き込みの結果が読める(必要に応じてレプリケーションを待つ) |
| EVENTUAL | 待たない。自分の書き込みも、レプリケーションされるまで見えない場合がある |
| GLOBAL | 全リージョンのコミット済みデータが反映されるまで待つ |
| OFF | そのセッションでは書き込み転送を無効にする |
一貫性のレベルを上げるほどリージョン間のレプリケーション待ちが応答時間に乗ってきます。また、転送された書き込みはプライマリのWriterのmax_connectionsの枠を使います。使える枠の上限はapg_write_forward.max_forwarding_connections_percent(デフォルト25%)で制御されていて上限に達すると転送セッションは拒否されます。
ここまで見てきたとおり書き込み転送は使えるSQLの制約も多く接続数やレイテンシーへの影響もあります。便利な機能ではあるのですが、アプリケーション側で好き勝手に使われて、制約に引っかかってエラーが出たり、接続の上限に達して転送が拒否されたりすると原因の切り分けも含めてかなり大変です。
そのため個人的には機能として知っておきつつも基本的には使わない方針にして、積極的に使わせない方向に倒しておくのが好ましいかなと思っています。セカンダリリージョンから書き込みが必要な場合でも、まずはグローバルライターエンドポイント経由でプライマリに書き込む形を検討するのが無難です。
5. 切り替え方式の整理
Global DBでプライマリリージョンを変える方法は3つあります。
| 観点 | スイッチオーバー | マネージドフェイルオーバー | 手動フェイルオーバー(デタッチ) |
|---|---|---|---|
| 用途 | 計画的な切り替え(メンテナンス、リージョンローテーション、障害後の切り戻し) | リージョン障害時の復旧 | マネージドが使えない場合(バージョン不一致など) |
| 前提 | 全クラスターが正常 | プライマリが障害でも実行可 | — |
| RPO | 0(同期を待ってから切り替える) | 秒単位(ラグ分のデータロスあり) | 秒単位(ラグ分のデータロスあり) |
| RTOの目安 | 対象バージョンでは通常30秒未満 | 数分程度 | 手順次第 |
| トポロジー | 維持される | 維持される(旧プライマリは回復後に自動でセカンダリとして再参加) | 維持されない(Global DBを組み直す) |
| CLI | switchover-global-cluster |
failover-global-cluster --allow-data-loss |
remove-from-global-cluster |
5.1 スイッチオーバー
以前はマネージド型の計画的フェイルオーバーと呼ばれていた機能です。
動作の流れは以下のとおりです。
- 切り替え先のセカンダリがプライマリと完全に同期するのを待つ
- 旧プライマリを読み取り専用にする
- 切り替え先のセカンダリのReaderをWriterに昇格する
同期を待ってから切り替えるのでRPOは0です。その代わり、ラグが大きいほど切り替えに時間がかかります(公式ドキュメントでも、ラグの値はスイッチオーバーの所要時間に正比例すると記載されています)。
Aurora PostgreSQL 16.8、15.12、14.17、13.20以降(Aurora MySQLは3.09以降)では、読み書きの復旧時間が通常30秒未満に短縮されています。アップグレードすれば追加の設定なしで適用されます。
5.2 マネージドフェイルオーバー
リージョン障害時に使う方式です。スイッチオーバーとは異なりセカンダリとの同期を待たずに切り替えます。そのため、レプリケーションされていなかった書き込みは失われます。
ただし、失ったデータを後から救う仕組みも用意されています。旧プライマリのリージョンが回復すると、Auroraは旧ストレージボリュームのスナップショットを取得しようとします。成功すると、以下の名前のスナップショットが作られます。
rds:unplanned-global-failover-<旧プライマリのクラスター名>-<タイムスタンプ>
このスナップショットはシステムスナップショット扱いで、旧プライマリのバックアップ保持期間が過ぎると消えます。失ったデータの調査に時間がかかりそうな場合は手動スナップショットとしてコピーしておく必要があります。
その後、旧プライマリのリージョンにはストレージボリュームが新しく作られセカンダリとして自動で再参加します。セカンダリの再構築にはストレージのサイズやリージョン間の距離によって数分〜数時間かかるとされています。
5.3 手動フェイルオーバー
エンジンのパッチレベルが揃っていないなど、マネージドフェイルオーバーが使えない場合の手段です。
セカンダリクラスターをGlobal DBから切り離す(デタッチする)とレプリケーションが即座に止まりそのクラスターは読み書き可能な単独のクラスターに昇格します。その後、そのクラスターをプライマリとしてGlobal DBを組み直します。
デタッチしたクラスターはGlobal DBの外に出るため、グローバルライターエンドポイントの向き先にはなりません。アプリケーションの接続先は切り替える必要があります。セカンダリのクラスターエンドポイントから-roを外した文字列が新しいクラスターエンドポイントになります。
# 昇格前(セカンダリ)
my-global.cluster-ro-aaaaaabbbbbb.ap-northeast-3.rds.amazonaws.com
# 昇格後
my-global.cluster-aaaaaabbbbbb.ap-northeast-3.rds.amazonaws.com
5.4 切り替えのためのバージョン要件
スイッチオーバー/マネージドフェイルオーバーを使うには、プライマリとセカンダリのメジャーバージョンとマイナーバージョンが一致している必要があります。パッチレベルまで一致が必要かどうかはエンジンとバージョンによって異なります。
いざという時に「バージョンがずれていてマネージドフェイルオーバーが使えない」という事態は避けたいので、バージョン管理は7.3で触れる運用と合わせて考える必要があります。
5.5 2本目で確認すること
ここまでは公式ドキュメントに書かれている仕様です。2本目では、東京・大阪で実際にGlobal DBを構築して、以下を確認する予定です。
- スイッチオーバーで書き込みが止まる時間は本当に30秒未満なのか、RPOは本当に0なのか
- フェイルオーバーで実際にどのくらいのデータが失われるのか
- グローバルライターエンドポイントのDNSはどのタイミングで切り替わるのか
- 旧プライマリが再参加するまでにどのくらいかかるのか
6. rds.global_db_rpoでRPOを制御する
Aurora PostgreSQLのGlobal DBにはRPOの上限を設定できるrds.global_db_rpoというパラメータがあります。Aurora MySQLにはない、PostgreSQL独自の機能です。
| 項目 | 内容 |
|---|---|
| 設定場所 | DBクラスターパラメータグループ |
| 単位 | 秒 |
| 設定可能範囲 | 20〜2147483647 |
| デフォルト | 未設定(SHOWすると-1) |
| 種別 | 動的パラメータ(再起動不要) |
設定するとAuroraは全セカンダリのRPO lagを監視して、以下のように動作します。
- 少なくとも1つのセカンダリのRPO lagが設定値未満 → トランザクションはそのままコミットされる
- 全てのセカンダリのRPO lagが設定値を超えた → プライマリのコミットを止める
つまり、「RPOを守れないくらいならコミットさせない」というパラメータです。止まったセッションはwaitイベントとして見え、PostgreSQLのログにも記録されます。ラグが解消されればコミットは再開されます。
RPOを保証できる代わりに、レプリケーションが遅れるとプライマリの可用性を差し出すトレードオフになります。動的パラメータなので問題が起きたらすぐにリセットできる点は救いです。
注意点が2つあります。
①2リージョン構成ではセカンダリ側のパラメータグループをデフォルトのままにする
セカンダリが1つしかない構成でセカンダリ側のパラメータグループにもrds.global_db_rpoを設定していると、フェイルオーバー後に新プライマリでトランザクションが止まる可能性があります。フェイルオーバー直後は旧プライマリのリージョンが再構築されるまでセカンダリが存在しないためです。公式ドキュメントでは旧プライマリのリージョンの再構築が終わってから設定するよう推奨されています。
②有効なままだとメジャーバージョンアップグレードができない
rds.global_db_rpoが有効な状態では、Aurora PostgreSQLのメジャーバージョンアップグレードができません。アップグレードの前に無効にする手順を運用手順書に組み込んでおく必要があります。
個人的にはRPOに厳しい要件がない限りは無理に設定せず、AuroraGlobalDBRPOLagのアラームで検知するところから始めるのがいいかなと思っています。コミットが止まるのはアプリケーションから見るとほぼ障害なので、RPOを守ることとサービスを止めないことのどちらを優先するか、業務側と合意してから設定すべきパラメータだと思います。
ちなみに今回の案件では、導入で触れたとおりRPO約1分という要件があったためrds.global_db_rpoを60秒に設定したうえで、AuroraGlobalDBRPOLagのアラームでも監視する構成にしています。パラメータでRPOの上限を担保しつつ、ラグの状況はアラームで把握するという役割分担ですね。
ただ、ラグの大きさはその時々の書き込み量やリージョン間の状況にも左右されるので、この設定で常に要件どおりに収まると言い切れるわけではありません。あくまで「要件に近づけるための仕組みを入れている」という位置づけで、実際にどの程度のラグで推移するのかは運用しながら見ていく必要があるかなと思っています。
7. 運用面での変更点
Global DBを採用した時に単一リージョンの場合と運用周りで何が変わるのかを最後に整理します。
| 項目 | 単一リージョン | Global DB |
|---|---|---|
| パラメータグループ | クラスター単位で管理 | リージョンごとに作成・管理。切り替えでは引き継がれない |
| 静的パラメータの変更 | 再起動はそのクラスター内で完結 | プライマリのWriterの再起動がセカンダリに波及する |
| マイナーバージョンアップグレード | 自動アップグレードを使える | 自動アップグレードは効かない。Global DB単位で揃えて上げる |
| クラスターの停止 | できる | できない |
| 認証情報の管理 | Secrets Managerとの統合を使える | 統合は使えない |
| 監視 | 1リージョン分のアラーム | リージョンごとに必要。ラグ系はセカンダリ側にしかない |
7.1 パラメータグループはリージョンごとに作る
パラメータグループはリージョン単位のリソースなので、当然ですが各リージョンのクラスターにそれぞれカスタムパラメータグループを作って割り当てます。
スイッチオーバー/フェイルオーバーで昇格したセカンダリは、旧プライマリのパラメータグループを引き継ぎません。前回の記事で整理したrds.force_ssl、log_statement、pgaudit.log、timezoneなどが、セカンダリ側だけデフォルトのままになっていると、切り替えた瞬間にSSLが強制されなくなったり、監査ログが出なくなったりします。
前回「PITRで復元されないもの」として整理したのと同じ構図で、切り替え時に引き継がれないものは以下のとおりです。
| 項目 | 対応 |
|---|---|
| DBクラスターパラメータグループ | 全リージョンで同じ設定のカスタムパラメータグループを用意しておく |
| CloudWatchアラーム・イベント | 全リージョンに同じアラームを用意しておく。ラグ系は切り替え後に見る場所が変わる |
| Performance Insights | クラスターごとに有効化する。リージョン追加時も引き継がれない |
| IAM、S3、Lambdaなど他サービスとの連携 | セカンダリリージョンからもアクセスできるように設定しておく |
| RDS Proxy | 新しいプライマリ側のProxyの読み書きエンドポイントに切り替える |
なお、Global DBのメジャーバージョンアップグレード中はカスタムパラメータグループを適用できないという制約もあります。アップグレード後に各リージョンで手動で割り当て直す必要があります。
7.2 プライマリの再起動がセカンダリに波及する
単一リージョンのAuroraとの違いで、個人的に一番見落としやすいと思っているのがここです。
公式ドキュメントによるとプライマリのWriterが再起動またはフェイルオーバーすると、セカンダリリージョンのReaderも再起動します。セカンダリクラスターは全てのReaderがプライマリと再同期するまで使えなくなります。
前回の記事で「pgAuditを後から有効化するにはshared_preload_librariesの変更と再起動が必要」と書きましたが、Global DBではこの再起動がセカンダリリージョンの読み取りにも影響します。セカンダリで読み取りワークロードを動かしている場合は、静的パラメータの変更やメンテナンスの影響範囲がリージョンをまたぐという点に注意が必要です。
基本設計の段階で静的パラメータを決め切っておくことの重要性は、Global DBではさらに増すかなと思います。
パラメータの変更が発生する場合には事前に関係各所との調整の上、業務影響がないタイミングでやるというのも重要な考慮事項になってきそうですね。
7.3 マイナーバージョンの管理
Global DBに参加しているクラスターでは、自動マイナーバージョンアップグレードの設定は効きません。設定自体はできますが設定しても効果を発揮しないという仕様があります。5.4で触れたとおり、マネージドな切り替えにはバージョンが揃っている必要があるので、各クラスターを個別に上げていくとバージョンがずれている瞬間が生まれます。
①マネージドなマイナーバージョンアップグレード
この点については2026年2月にAurora PostgreSQLのGlobal DB向けにマネージドなマイナーバージョンアップグレードが追加されました。1回の操作でプライマリと全セカンダリのアップグレードをまとめて実行でき、問題が起きた場合は自動でロールバックされます。
実行はグローバルクラスターに対してmodify-global-clusterコマンドで行います。
aws rds modify-global-cluster \
--global-cluster-identifier <グローバルクラスター識別子> \
--engine-version <アップグレード先のエンジンバージョン>
公式ドキュメントに記載されている特徴は以下のとおりです。
| 項目 | 内容 |
|---|---|
| 対象エンジン | Aurora PostgreSQLのみ(Aurora MySQLは非対応) |
| 対象のアップグレード | マイナーバージョンのみ。パッチバージョンは従来どおりシステム更新のメンテナンスアクションで適用する |
| 適用タイミング | 即時適用 |
| ダウンタイム | 最小限(ゼロではない) |
| 失敗時 | 自動で既存のバージョンにロールバックされる |
注意したいのは即時適用でダウンタイムもゼロではないという点です。メンテナンスウィンドウを待ってくれるわけではないので、実行するタイミングは自分たちで決めて、業務影響の少ない時間帯にコマンドを叩く必要があります。
Aurora PostgreSQLでGlobal DBを使うなら、マイナーバージョンアップグレードは手動で頑張るのではなくこの方法で行う前提で運用手順を組むのがいいかなと思います。
7.4 コスト
Global DBでは、通常のAuroraの料金に加えて以下がかかります。
- レプリケートされた書き込みI/O
- リージョン間のデータ転送料金
- セカンダリリージョンのストレージ・バックアップストレージ・インスタンス
ここで注意したいのがI/O-Optimizedとの関係です。I/O-Optimizedにすると通常の読み書きのI/O料金はかかりませんが、レプリケートされた書き込みI/Oは、StandardでもI/O-Optimizedでも課金されます。
「I/O-OptimizedにしたからI/O料金は気にしなくていい」と思っていると、セカンダリリージョンを増やしたときに想定外の請求が来るかもしれません。セカンダリリージョンが増えるほど、この料金はリージョン数に比例して増えていきます。3.4で触れたとおりクラスターを停止できないので、検証環境でも2リージョン分のインスタンス料金がかかり続けます。
まとめ
本記事では、Aurora Global Databaseの仕様を単一リージョンのAuroraとの違いという観点で整理しました。
- Global DBはストレージ層でレプリケーションするため、ヘッドレス構成でも複製が続く
- 「この瞬間に失われるデータ量」を表すのはdurability lagではなくRPO lag
- グローバルライターエンドポイントで接続先は変えずに済むが、リージョン間のネットワークとDNSキャッシュは別途考える必要がある
- スイッチオーバーはRPO 0、フェイルオーバーはラグ分のデータロスがあり、旧プライマリのスナップショットは保持期間で消える
-
rds.global_db_rpoはRPOを守る代わりにコミットを止めるパラメータ - パラメータグループ・監視・認証情報・バージョン管理・コストは、単一リージョンのときとは別物として設計し直す必要がある
検証を進める中でGlobal DBを採用する前に最低限以下は決めておくのがいいかなと思います。
| 決めること | 理由 |
|---|---|
| セカンダリにインスタンスを置くか(ヘッドレスにするか) | コストとRTOのトレードオフ |
| 接続先をグローバルライターエンドポイントに統一できるか | 切り替え時の接続先変更とスプリットブレインのリスクを減らすため |
| 全リージョンのパラメータグループ・アラームをどう揃えるか | 切り替えでは引き継がれないため。IaCで同じ定義を各リージョンに展開しておくのが現実的 |
| 認証情報をどう管理するか | Secrets Managerとの統合が使えないため |
rds.global_db_rpoを設定するか |
RPOの保証と可用性のどちらを優先するかの業務判断が必要 |
| マイナーバージョンをどう上げるか | 切り替えにはバージョンの一致が必要なため |
次回は実際に東京・大阪間でGlobal DBを構築して、スイッチオーバーとフェイルオーバーで何が起きるのかを検証します。本記事で整理した仕様が実際にどう動くのかを数字で確認する予定です。
Aurora Global Databaseの採用を検討している方の参考になれば幸いです。
参考資料
- Amazon Aurora Global Database の使用
- Amazon Aurora Global Database introduces support for up to 10 secondary Region clusters
- Amazon Aurora Global Database のモニタリング
- Amazon Aurora Global Database でのスイッチオーバーまたはフェイルオーバーの使用
- Amazon Aurora Global Database の設定要件
- セカンダリリージョンでのヘッドレス Aurora DB クラスターの作成
- Amazon Aurora Global Database への接続
- Aurora PostgreSQL グローバルデータベースでの書き込み転送の使用
- Amazon Aurora の料金
- Amazon Aurora Global Database のアップグレード
- Amazon Aurora Global Database now supports managed minor version upgrades
- Aurora DB クラスターのバックアップと復元の概要





