RDS スナップショット復元が遅い原因と対処

目次
  1. 結論:復元直後の遅さはEBSの遅延ロードが主因、本番前に「全ブロックを一度読む」
  2. なぜ復元直後だけ遅いのか:スナップショットとEBSボリュームの関係
  3. 切り分け手順:ファーストタッチペナルティか、別の原因か
  4. 対処:復元後にデータブロックを一度触っておく
  5. よくある誤解
  6. よくある質問
  7. まとめ:復元手順書に「ウォームアップ」を一行追加する
このテーマのまとめRDS・Aurora 運用・トラブル解決ガイド|仕組み・障害切り分け・性能監視の全体像
本記事にはプロモーション(広告)が含まれています。

RDSのスナップショットやポイントインタイムリカバリ(PITR)から復元したインスタンスが「同じクエリなのに本番より遅い」「アプリがタイムアウトする」。しかも時間が経つと勝手に改善するので、障害なのか設定ミスなのか待てば直るのか、判断しづらい。

主因はRDS(非Aurora)が使うAmazon EBSボリュームの**ファーストタッチペナルティ(遅延ロード/Lazy Loading)**です。仕組みとCloudWatchでの切り分け、エンジン別のウォームアップ手順、復旧訓練やRTO見積もりへの反映方法をまとめます。

結論:復元直後の遅さはEBSの遅延ロードが主因、本番前に「全ブロックを一度読む」

RDS(非Aurora)のDBインスタンスはストレージにEBSボリュームを使います。スナップショットから作られたボリュームはブロックの実体をバックグラウンドで取得する方式で、まだ取得が終わっていないブロックに初めてアクセスすると、その場でAmazon S3へ取りに行くため追加のレイテンシが乗ります。一度アクセスされたブロックはEBSボリューム上に載るので、2回目以降は通常のパフォーマンスに戻ります。

復元直後の遅さは、初回アクセス分のコストを前払いしていないだけです。本番トラフィックを流す前に、自分で全ブロックを一度読んでおけば済みます。

今すぐ確認する3点(復元からの経過時間・ReadLatency・時間経過での改善)

焦っているときは、次の3点だけ順番に見てください。

  1. 復元直後のタイミングか。スナップショット復元またはPITR復元の直後なら、ファーストタッチペナルティの可能性が高い。復元が何時間前なのか、その間に本番相当の読み取りが流れたのかを押さえます。
  2. CloudWatchのReadLatency/WriteLatencyが通常運用時より高くないか。読み取りレイテンシが普段の水準から離れていれば、I/O 1件あたりのコストが上がっている状態です。
  3. 時間経過とともにレイテンシが改善しているか。アクセスされたブロックから順に解消するため、右肩下がりになります。横ばいや悪化なら別の原因を疑ってください。

3点が揃えば、ほぼ遅延ロードと判断してウォームアップに進めます。

本番切り替え前にやること/やらなくてよいこと

やることは1つだけ。アプリケーションを向ける前に、主要なテーブルとインデックスのデータブロックへ一度アクセスしておく。アクセス済みブロックはその後遅延しないので、毎日繰り返す必要はありません。

やらなくてよいこともはっきりさせておきます。インスタンスクラスのスケールアップは、遅延ロードがI/O待ちでCPU不足ではないため根本解決になりません。ストレージタイプの変更やプロビジョンドIOPSへの変更も、恒久的にI/O性能が足りないなら別途検討すべき話で、復元直後の一時的な遅さへの対策としては筋が違います。復元のやり直しは同じことが起きるだけ。パラメータの当てずっぽうなチューニングは、原因が別のところにあった場合にあとの切り分けを難しくします。

なぜ復元直後だけ遅いのか:スナップショットとEBSボリュームの関係

スナップショットの実体はS3側にある:初回アクセスでブロックを取りに行く

EBSスナップショットは、ボリュームのブロックをS3側に保管したものです。スナップショットから新しいボリュームを作るとき、全ブロックのコピーを待ってから使えるようになるわけではありません。ボリュームはすぐavailableになり、ブロックの実体はバックグラウンドで順次取得されます。

このため、まだ取得されていないブロックへの読み取りはS3からの取得を待たされます。DBからすると、いつもと同じ8KB(あるいは16KB)のページ読み取りをしただけなのに、返ってくるまでがやたら遅いという見え方になります。EC2のEBSでも共通する挙動で、RDSも同じストレージを使っている以上そのまま起きます。

ファーストタッチペナルティが「2回目以降は消える」理由

一度アクセスされたブロックは、以降EBSボリューム上に存在する状態になります。2回目のアクセスではS3に取りに行く必要がなく、そのボリュームタイプ本来のレイテンシで返ります。

DBのキャッシュから消えたらまた遅くなる、という話ではありません。DBを再起動して共有バッファが空になっても、EBS側の実体はボリューム上にあるのでペナルティは再発しない。「初期化は一度だけでよい」のはこの意味です。

DBバッファキャッシュのウォームアップとは別物:2段階のキャッシュを分けて考える

復元後の性能問題では、2つのレイヤーを混ぜると混乱します。レイヤー1はEBSブロックの実体化、つまりファーストタッチペナルティで、解消すれば永続し、DB再起動でも失われません。レイヤー2はDBのバッファキャッシュ(PostgreSQLのshared_buffers、MySQL/InnoDBのbuffer pool、Oracleのバッファキャッシュ、SQL Serverのバッファプール)で、プロセスのメモリ上にあるため再起動やフェイルオーバーで失われ、再度ウォームアップが必要になります。

復元直後の「時間が経つと改善する」現象は主にレイヤー1の話です。本番トラフィックを流し始めてからの立ち上がりの鈍さには、レイヤー2も関わってきます。

なおPostgreSQLのシーケンシャルスキャンは、大きなテーブルに対してリングバッファ(バルクリード用の小さな専用バッファ)を使うため、全件スキャンしてもshared_buffersは埋まりません。「全件スキャンしたのにshared_buffersに乗っていない」のは正常で、レイヤー1の解消という目的は達成できています。レイヤー2まで温めたいなら、後述のpg_prewarmのbufferモードを使います。

Auroraにおけるバッファキャッシュのウォームアップ(Cluster Cache Managementなど)の考え方は、Aurora インスタンスクラス変更のダウンタイム最小化手順でも触れています。

Auroraで同じ現象が起きないのは共有ストレージだから

Auroraは3AZに6コピーを分散する専用の共有ストレージ層を使います。スナップショットからの復元もこのストレージ層の仕組みで行われるため、EBSのファーストタッチペナルティという概念自体が該当しません。

アーキテクチャの違いは、レプリカラグやストレージ側の挙動にも直結します。Aurora側の仕組みはAuroraレプリカラグ監視|AuroraReplicaLagでも扱っています。

ただしAuroraでも、復元したクラスタのバッファキャッシュは空から始まります。「Auroraなら復元直後から本番と同じレスポンスが出る」という期待は行き過ぎで、レイヤー2のウォームアップには意味があります。

切り分け手順:ファーストタッチペナルティか、別の原因か

CloudWatchのReadLatency / ReadIOPS / ReadThroughputの見方と判断基準

見るべきメトリクスは4種類です。

  • ReadLatency / WriteLatency:I/O 1件あたりの所要時間
  • ReadIOPS / WriteIOPS:I/Oの件数
  • ReadThroughput / WriteThroughput:帯域
  • BurstBalance(gp2)、EBSIOBalance% / EBSByteBalance%(該当インスタンスクラス):クレジット残の消費状況

判断の軸は「レイテンシが高い理由が、件数の多さで説明できるか」です。ReadLatencyが高いのにReadIOPSやReadThroughputがボリュームの上限に達していないなら、1件あたりが遅いということで遅延ロードに整合します。逆にReadIOPSやReadThroughputが上限に張り付いた結果レイテンシが上がっているなら、スロットリングや容量設計の問題です。gp2ならBurstBalanceの枯渇、gp3なら設定済みIOPS/スループットの上限、インスタンスクラス側のEBS帯域上限を順に確認します。時系列でレイテンシが単調に改善していれば遅延ロードの解消過程、横ばいなら別原因。

比較対象として、復元元の本番インスタンスの同一メトリクスを並べるのが一番確実です。絶対値の閾値を決め打ちするより、普段の水準からの乖離で見るほうが誤判定が少ない。具体的な上限値や課金の扱いは変わることがあるので、該当するストレージタイプとインスタンスクラスの仕様は公式ドキュメントで確認してください。

同じクエリを2回流して実行時間が縮むか試す

机上の議論より早い。アプリで遅いと言われているクエリ、あるいは大きめのテーブルへの集計クエリを連続で2回実行します。

-- PostgreSQL の例
EXPLAIN (ANALYZE, BUFFERS) SELECT count(*) FROM <テーブル名>;
-- 同じものをもう一度
EXPLAIN (ANALYZE, BUFFERS) SELECT count(*) FROM <テーブル名>;

2回目が明確に速くなり、BUFFERSのshared read(ディスクから読んだブロック数)が減っていれば、I/O由来と確認できます。2回目も同じだけ遅いなら、実行計画やロック待ち、CPU側を疑う段階です。

注意点として、2回目が速い理由がEBSの実体化なのかDBのバッファキャッシュなのかは区別がつきません。切り分けとしては「I/O起因である」ことが分かれば十分なので、まずは前に進めて構いません。

待機イベントと実行計画を見て「I/O以外」の可能性を潰す(統計情報、インスタンスクラス、ストレージタイプ)

待機イベントを見るのが最短です。Performance Insightsを有効にしていれば一目で分かりますが、SQLでも確認できます。

-- PostgreSQL:I/O 待ちのセッションを確認
SELECT pid, wait_event_type, wait_event, state, query
  FROM pg_stat_activity
 WHERE wait_event_type IS NOT NULL;

wait_event_type = 'IO'でDataFileReadが並ぶなら、データファイル読み取り待ちです。Oracleならdb file scattered read/direct path read、SQL ServerならPAGEIOLATCH_*、MySQLならPerformance Insights上のI/O系待機が同じ位置づけです。これらが支配的ではなくLockやLWLock、CPUが主体なら原因は別にあります。

I/O以外で復元後に遅くなる典型は3つあります。

1つ目はパラメータグループの違い。復元時にカスタムパラメータグループを指定し忘れてデフォルトのまま起動すると、shared_buffersやinnodb_buffer_pool_size、work_mem、並列度の設定が本番と変わります。復元直後に必ず確認したい項目です。

2つ目はインスタンスクラスやストレージタイプの違い。復元時に別のクラスやストレージタイプを選べるため、検証用の小さい構成で復元したまま本番相当の負荷をかけて「遅い」と言っているケースがあります。gp2は容量に比例した性能、gp3は設定値、io1/io2はプロビジョンド値、という前提の差も押さえます。

3つ目は統計情報。ここは誤解されがちですが、スナップショット復元は物理的な復元なので、PostgreSQLのpg_statistic、Oracleのディクショナリ統計、InnoDBの永続統計などは基本的にそのまま引き継がれます。「復元したら統計が消えて実行計画が変わった」はスナップショット復元では起こりにくい。実行計画が変わっているなら、統計より先にパラメータグループとインスタンスクラス(並列度やメモリ関連パラメータが変わる)を確認したほうが当たります。ダンプからの論理リストアで移したなら統計は空なので、ANALYZE/DBMS_STATS/ANALYZE TABLEが必要です。

復元とは別軸の性能劣化・接続断の切り分けは、RDS・Aurora 運用・トラブル解決ガイドに全体像をまとめています。

検証環境で再現して初期化にかかる時間を測る

再現手順は単純です。

  1. RDSのスナップショットからDBインスタンスを復元する
  2. 復元直後にアクセスし、レスポンスタイムが通常より遅いことを確認する
  3. 主要テーブルを全件読み込んだ後に、レスポンスタイムが改善することを確認する

2〜3にかかった時間を記録してください。所要時間はデータ量、ストレージタイプ、IOPS設定、インスタンスクラスのEBS帯域、並列度で大きく変わるため、一般的な目安を当てはめても意味がありません。自分の環境で測った値だけが、後述するRTO見積もりに使える数字です。

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

EC2・IAM・RDSの運用やバックアップ/リストアを基本から解説しており、復元後の運用設計の参考になります。

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

対処:復元後にデータブロックを一度触っておく

RDSではddやfioによるボリューム初期化が使えない理由

EC2のEBSなら、ボリューム全体を読み出してファーストタッチを済ませる手段としてddやfioでの初期化が案内されています。しかしRDSはOSにログインできないため、この方法を使えません。

代わりにDBエンジンの上から「全データブロックを読むクエリ」を実行して同じ効果を得ます。DB経由の読み取りでも最終的にはボリューム上の同じブロックにアクセスするので、ファーストタッチは解消されます。

考え方は共通で、テーブル本体だけでなくインデックスも読む。これだけです。インデックスを読み忘れると、本番トラフィックでインデックス検索が走ったときに同じ遅さが出ます。

PostgreSQL:pg_prewarm・全件スキャン・VACUUMの使い分けとインデックスの扱い

もっとも素直なのはpg_prewarm拡張です。

CREATE EXTENSION IF NOT EXISTS pg_prewarm;

-- read モード:ブロックを読むが shared_buffers は使わない
SELECT pg_prewarm('<テーブル名>', 'read');

-- buffer モード:shared_buffers にも載せる
SELECT pg_prewarm('<テーブル名>', 'buffer');

モードの使い分けはこうなります。readはブロックを読むだけで、EBSの実体化(レイヤー1)が目的ならこれで十分。既存のshared_buffersの内容を追い出さない利点もあり、復元後のウォームアップでは基本これを選びます。bufferはshared_buffersにも載せるので、本番切り替え直後の立ち上がりまで良くしたい場合に、重要なテーブルとインデックスへ限定して使います。全テーブルに対して実行するとshared_buffersを使い切るだけなので、対象は絞ってください。prefetchは非同期プリフェッチですが、プラットフォーム依存があり、確実性を取るならreadが無難です。

インデックスとTOASTを忘れないのが実務上のポイント。pg_prewarmはrelation単位なので、テーブルを指定してもそのインデックスやTOASTリレーションは対象外です。まとめて回すならpg_classから対象を列挙します。

-- テーブル・インデックス・TOAST をまとめて read する例
SELECT c.oid::regclass AS rel,
       pg_size_pretty(pg_relation_size(c.oid)) AS size,
       pg_prewarm(c.oid, 'read')
  FROM pg_class c
  JOIN pg_namespace n ON n.oid = c.relnamespace
 WHERE c.relkind IN ('r', 'i', 't', 'm')
   AND n.nspname NOT IN ('pg_catalog', 'information_schema')
 ORDER BY pg_relation_size(c.oid) DESC;

pg_prewarmが使えない場合の代替も押さえておきます。

全件スキャンはSELECT count(*) FROM <テーブル名>;で手軽ですが、プランナが小さいインデックスを使ったindex-only scanを選ぶとテーブル本体を読みません。EXPLAINでSeq Scanになっているか確認するか、SELECT count(*) FROM (SELECT * FROM <テーブル名> OFFSET 0) t;のように本体を読ませる形にします。インデックスはSET enable_seqscan = off;で索引スキャンを強制するか、pg_prewarmに寄せたほうが確実です。

VACUUMも使えますが注意点が2つ。スナップショット復元では可視性マップも復元されているため、通常のVACUUMはall-visibleなページをスキップして全ブロックを読まない可能性があります。全ページを読ませたいならVACUUM (DISABLE_PAGE_SKIPPING) <テーブル名>;を使ってください。もう1つ、VACUUMは書き込みを伴いWALを生成するため、読み取りだけで済むpg_prewarmよりI/Oコストが高い。VACUUM FULLはテーブルを書き換えるので、ウォームアップ目的には不適切です。

MySQL / MariaDB・Oracle・SQL Serverで全ブロックを読ませるクエリの考え方

エンジンが変わっても目的は同じで、テーブル本体(クラスタ化インデックス/ヒープ)と全セカンダリインデックスのブロックを一度読みます。

MySQL / MariaDB(InnoDB)

-- クラスタ化インデックス(=データ本体)を読ませる
SELECT COUNT(*) FROM <テーブル名> FORCE INDEX (PRIMARY);

-- セカンダリインデックスを読ませる(インデックスごとに実行)
SELECT COUNT(*) FROM <テーブル名> FORCE INDEX (<インデックス名>);

CHECK TABLE <テーブル名>;も全体を読む手段です。全テーブルを一括でやりたいなら、クライアント側からmysqldumpで全データを読み出して出力を捨てる手も実務的で、主キー順に全行を読むためデータ本体の実体化に使えます。なおinnodb_buffer_pool_dump_at_shutdown/_load_at_startupはレイヤー2のバッファプールの話で、EBSの実体化とは別物です。

Oracle

-- テーブル本体(フルスキャン)
SELECT /*+ FULL(t) */ COUNT(*) FROM <テーブル名> t;

-- インデックス(インデックス高速フルスキャン)
SELECT /*+ INDEX_FFS(t <インデックス名>) */ COUNT(<列名>) FROM <テーブル名> t;

大きなテーブルのフルスキャンはダイレクトパス読み取りになりバッファキャッシュを経由しませんが、EBSのブロックには触るのでレイヤー1の目的は果たせます。DBMS_STATSを推定率100%で回す方法も全ブロックを読みますが、統計が書き換わるため、本番と同じ実行計画を維持したい場面では避けたほうが無難です。

SQL Server

-- クラスタ化インデックス/ヒープを読む
SELECT COUNT_BIG(*) FROM <テーブル名> WITH (INDEX(0));

-- 非クラスタ化インデックスを読む
SELECT COUNT_BIG(*) FROM <テーブル名> WITH (INDEX(<インデックス名>));

DBCC CHECKDBも全体を読みますが、負荷と実行時間が大きいので、ウォームアップ目的なら対象を絞ったクエリのほうが制御しやすい。読み取りの進み具合はsys.dm_io_virtual_file_statsのio_stall_read_ms/num_of_readsの推移で確認できます。

データ量が大きいときの進め方(優先順位付け、並列度、I/Oクレジットへの配慮)

数TB規模になると「全部読む」が現実的な時間に収まらないことがあります。そのときは優先順位をつけます。

まず本番で実際にアクセスされるテーブルとインデックスから。クエリログやpg_stat_user_tables、sys.dm_db_index_usage_statsなどの統計(復元元の本番側で取得したもの)を使って、アクセス頻度の高い順に並べます。サイズの大きいものは後回しでも構わない場合があり、巨大だがバッチでしか参照されないテーブルより、小さくてもOLTPの主要パスにあるインデックスのほうが優先度は高い。コールドなアーカイブ領域は、本番公開後にバックグラウンドで読み進める運用もありです。

並列度とI/Oクレジットの扱いにも注意します。並列化でスループットは上がりますが、ボリュームのIOPS/スループット上限、インスタンスクラス側のEBS帯域上限で頭を打ちます。上げすぎると、ウォームアップ自体がスロットリングで遅くなる。gp2ではバーストクレジットを使い切るリスクがあるので、BurstBalanceを監視しながら進め、枯渇しそうなら並列度を落とすか、ウォームアップの間だけIOPSを確保できるストレージ設定にする判断もあります。

ウォームアップ中のI/Oも課金対象の読み取りとしてカウントされるため、巨大なデータを一度に読む場合はコスト面も見ておきます(AuroraのI/Oカウントの考え方はAurora I/O 料金の見積もり方が参考になります。RDSと課金モデルは異なりますが、何がカウントされるかを考える姿勢は共通です)。

進め方としては、サイズ降順に1リレーションずつ、進捗をログに残しながら流すのが運用しやすい。途中で止まっても、読み終わった分の実体化は無駄になりません。

復元から本番公開までの手順テンプレートとRTOへの組み込み

手順書に落とすと、だいたい次の形です。

# 1. 復元(パラメータグループ・インスタンスクラス・ストレージタイプを本番相当で指定する)
aws rds restore-db-instance-from-db-snapshot \
  --db-instance-identifier <新インスタンス名> \
  --db-snapshot-identifier <スナップショット名> \
  --db-instance-class <インスタンスクラス> \
  --db-parameter-group-name <パラメータグループ名> \
  --storage-type <ストレージタイプ>

# 2. available になるまで待つ
aws rds wait db-instance-available --db-instance-identifier <新インスタンス名>

# 3. 設定が本番相当か確認(クラス・ストレージ・パラメータグループ)
aws rds describe-db-instances --db-instance-identifier <新インスタンス名>

この後に続く手順は次のとおりです。

  1. ウォームアップ。上記のエンジン別クエリで全ブロックを読む(サイズ降順、進捗記録)
  2. CloudWatchでReadLatencyが通常水準に戻ったことを確認
  3. 代表クエリを2回流し、1回目と2回目の差が小さいことを確認(差が大きければ未ウォームの領域が残っている)
  4. 接続先の切り替え(エンドポイント変更/DNS切り替え)
  5. 切り替え後しばらくはレイテンシとエラー率を重点監視

RTOには「復元+ウォームアップ+検証までの時間」で見積もりを入れます。災害復旧訓練でスナップショット復元を行う際は、ウォームアップにかかった時間も記録して次回の見積もりに反映してください。データ量は増えていくので、年に一度は測り直す運用が望ましい。

なお、復元後にMulti-AZ化やリードレプリカ作成を行う場合、それ自体が追加のI/Oを発生させます。ウォームアップと同時に走らせると互いに遅くなるので、順序を決めておきます。Multi-AZの挙動そのものについてはRDS Multi-AZ フェイルオーバー原因の確認手順も参考にしてください。

よくある誤解

「復元直後からフルパフォーマンスが出る」

もっとも多い誤解です。EBSベースのRDSでは、スナップショットから作ったボリュームに初回アクセス時のペナルティがあります。復元が完了してavailableになったことは、本番と同じ性能が出ることを意味しません。移行計画やカットオーバー手順を引くときは、ここに時間を確保しておきます。

「遅いのはインスタンスクラスやストレージ設定を間違えたから」

可能性はあるので確認はすべきですが、遅延ロードならクラスを上げても直りません。切り分けの順序としては、まず「復元直後か」「ReadLatencyが高いか」「時間経過で改善しているか」を見る。改善傾向があるなら遅延ロードです。そこでスケールアップに走ると、原因不明のままコストだけ増えます。ウォームアップ後も遅いなら、そこで初めてクラス・ストレージタイプ・パラメータグループを本番と突き合わせます。

「初期化が終わるまでDBにアクセスできない」

アクセス自体は可能です。ボリュームの実体化が進んでいる最中でも読み書きはできます。パフォーマンスが低下しているだけ、という状態です。

だからこそ「気づかずに本番を向けてしまう」事態が起きます。アプリのタイムアウト設定が厳しいと、復元直後にエラーが大量発生します。アクセスできるからといって、ウォームアップを省略してよいわけではありません。

「AuroraでもRDSと同じ対策が必要」

Auroraは共有ストレージアーキテクチャのため、EBSのファーストタッチペナルティには該当しません。RDS(非Aurora)とAuroraで復元後の挙動が異なる点は、手順書を分けて書くべきポイントです。

ただし前述のとおり、バッファキャッシュが空から始まるのはAuroraでも同じ。「ストレージ起因の遅さはない」「メモリ上のキャッシュは温まっていない」と整理しておくと、どちらのエンジンでも判断を間違えません。

よくある質問

復元直後の遅さは放置していれば直る?

アクセスされたブロックから順に解消されるので、本番トラフィックを流し続ければ徐々に改善します。ただし放置で直るのは、実際にアクセスされたブロックだけ。月次バッチでしか触らないテーブルは、翌月のバッチ実行時に初めてペナルティを払います。「本番公開してしばらく経ったから大丈夫」と思っていたら、月初のバッチが異様に遅い、という形で後から出てきます。

また、改善するまでの間はユーザーが遅さを体感します。SLAやタイムアウト設定との兼ね合いで許容できないなら、やはり先に読んでおくべきです。

PITRから復元した場合も同じことが起きる?

はい。PITRも内部的にはバックアップからEBSボリュームを作り、そこにトランザクションログを適用する流れなので、復元されたボリュームには同じ遅延ロードの特性があります。スナップショット復元かPITRかで対処を変える必要はありません。

ウォームアップは毎回やる必要がある?

そのインスタンスについては一度だけです。一度読み込んだブロックはその後遅延しないため、DBを再起動しても、インスタンスクラスを変更しても、EBS側の実体化はやり直しになりません。

ただし、新しくスナップショットから復元したインスタンスは別物。復元のたびに、そのインスタンスで一度ウォームアップが必要です。開発環境を毎週本番スナップショットから作り直している運用では、作成スクリプトにウォームアップを組み込んでおくと余計な問い合わせが減ります。

復旧時間(RTO)の見積もりには何を加えておけばいい?

最低限、次の3つを足してください。

  1. スナップショット/PITRからの復元完了までの時間
  2. ウォームアップ(全ブロック読み込み)にかかる時間
  3. 切り替え前の動作確認・検証の時間

2は自分の環境で実測するしかありません。データ量・ストレージタイプ・IOPS・インスタンスクラス・並列度で変わるため、訓練のたびに測って記録に残します。あわせて「全ブロック読むのが時間的に無理なら、どのテーブルまで優先して読むか」を決めておくと、緊急時に判断で詰まりません。

まとめ:復元手順書に「ウォームアップ」を一行追加する

要点を整理します。

  • RDS(非Aurora)はEBSをストレージに使うため、スナップショットやPITRから復元したボリュームには**ファーストタッチペナルティ(遅延ロード)**がある。初回アクセス時にS3からブロックを取得するため遅い
  • 一度アクセスされたブロックは以降EBSボリューム上に載るので、2回目からは通常性能に戻る。初期化は一度だけでよい
  • 切り分けは「復元直後か」「ReadLatencyが普段より高いか」「時間経過で改善しているか」の3点。改善傾向があれば遅延ロード、横ばいならパラメータグループ・インスタンスクラス・ストレージタイプ・待機イベントを見る
  • RDSはOSにログインできずdd/fioを使えないので、DB側からテーブル本体とインデックスを全件読むクエリで代替する(PostgreSQLならpg_prewarmのreadモードが扱いやすい)
  • Auroraは共有ストレージなのでこのペナルティは該当しない。バッファキャッシュのウォームアップは別の話
  • 復旧訓練ではウォームアップ時間も含めてRTOを見積もる

やることは、復元手順書に「本番公開前に全ブロックを一度読む」という一行を追加するだけ。この一行の有無で、カットオーバー当日の慌て方が変わります。

ストレージタイプごとの性能上限、メトリクスの意味、拡張機能の対応状況、Auroraとの挙動差は、エンジンバージョンやサービス更新によって変わることがあります。手順書に落とす前に、AWSおよび各DBエンジンの公式ドキュメントで最新の仕様を確認してください。

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

データの扱い方から運用方法、SQLまで図解で学べ、DB側の挙動を理解する土台づくりに使えます。

楽天ブックスで詳しく見る Yahoo!ショッピングで見る