接続障害・サービスごとの復旧と成功したコミットの保持
同じ接続障害の後、業務の復旧・コミットの保持・再接続の負担はどうか?
結果の要約
この実験では、アプリケーションと DB の間の接続が一時的に切れたとき、接続が戻った後に正常な処理へ復帰するか、そしてすでに成功したコミットが消えたり二重に反映されたりしないかを確認しました。最小範囲(MVP)として、毎秒300件の注文業務を送っている最中に、負荷発生器から DB へ向かうパケットを30秒間破棄するよう経路を塞ぎました(ブラックホールルート)。これはクライアント側のネットワーク障害であり、DB 自体の障害やフェイルオーバー(failover)ではありません。
DSQL(D1)と Aurora Serverless v2(A2)のどちらも、遮断された30秒間のリクエストが接続エラーとタイムアウトで失敗し、150秒の測定区間全体の技術的失敗率は D1 20.6%、A2 20.7% でした。遮断時間が測定区間の20%であるため、遮断区間のリクエストはほとんど失敗し、残りの区間は正常に処理されたと解釈します。遮断を解除した後、新しい接続で最初の照会が成功するまで D1 は0.02秒、A2 は0.07秒でした。
最も重要な結果は整合性です。コミット応答を受け取れず成否が不明なリクエストは、業務 ID のレシートで確認してから再試行するように実装し、セル終了後にレシート・注文・元帳・在庫を突き合わせました。両サービスともコミットの消失、二重反映、在庫の不一致は0件でした。DSQL でも対照群と同じ方式(業務 ID のレシートとコミット有無の確認)を実装すれば、接続が切れた状況で整合性を守ることができました。
本番利用の観点
今回の試験範囲では、DSQL は接続が30秒切れても成功したコミットを失ったり二重に反映したりせず、接続が戻るとすぐに再接続しました。ただしこれはアプリケーションが業務 ID のレシートと「コミット有無が不明なときは確認してから再試行」を実装していたためで、この実装は DSQL と既存サービスの両方に必要です。遮断中のリクエストは両サービスとも失敗したため、復旧時間はネットワークが戻るまでの時間に左右されます。DSQL 内部の障害や AZ 障害での動作は、公開された障害注入手段がないため今回確認できず、Aurora のフェイルオーバー時間も測定していません。
確認する問い
同じ接続障害の後、業務の復旧・コミットの保持・再接続の負担はどうか? 今回の MVP は共通のクライアント接続障害だけを扱います。
実行条件
- リージョンと日時: ソウル(ap-northeast-2)、2026-09-29。A2 08:40–08:43 UTC、D1 10:00–10:04 UTC(D1 の最初の試行は測定ツールの不具合のため再実行)。
- 構成: D1 Aurora DSQL 単一リージョン、A2 Aurora PostgreSQL 16.15 Serverless v2(writer+reader、4–32 ACU)。データは E002 規模の2%。
- 負荷: E002 と同じ業務構成(商品照会40%、注文履歴30%、注文作成20%、取消10%)を固定到着率 300 TPS で送りました。ウォームアップ30秒 + 測定150秒で、測定開始40秒後から30秒間遮断しました。
- 障害注入: ランナーで DB エンドポイントが指す IP への経路を
ip route add blackholeで塞ぎ、30秒後に削除しました(D1 は IP 2つ、A2 は1つ)。 - 再試行: リクエストごとに最大3回、全体の締め切り2秒。コミット応答を受け取れなかったリクエストは、業務 ID のレシートを照会してコミットの有無を確認してから再試行します。
- 整合性検査: セルが作成した行だけを選び、レシート数がクライアントの確認したコミット数と不明件数の範囲内にあるか、注文・元帳・在庫の変化がレシートと一致するかを確認しました。
- 負荷発生器: D1
c6g.4xlarge、A2m7g.4xlargeの Spot ランナー。 - 計画から変わった点: Q の30%/80%の2つの負荷、条件ごとに3回、遮断前後10分の観測、サービスごとのフェイルオーバー(RDS reboot with failover、Aurora cluster failover)は実行しませんでした。
性能結果
| 構成 | 試行 TPS | 成功 TPS | 技術的失敗率 | 遮断解除後の最初の接続成功 | 不変条件違反 |
|---|---|---|---|---|---|
| D1 | 289.6 | 225.6 | 20.6% | 0.02秒 | 0件 |
| A2 | 292.4 | 237.6 | 20.7% | 0.07秒 | 0件 |
- 失敗の大部分は接続エラーでした(D1 の注文作成の失敗1,614件中1,572件、A2 は1,663件中1,619件)。残りは2秒の締め切り超過と少数の直列化競合でした。
- 遮断区間を含むセルのため、p99 は両サービスとも 1.5–1.9秒に増えました。遮断外の区間の遅延は E002 の結果と同じ水準です(D1 書き込み p95 約 29–30 ms、A2 約 9 ms)。
- D1 の取消リクエストのうち1,693件が「すでに取消済みの注文」として拒否されました。先行する E009 の試験が同じデータで取消を累積していたためで、整合性の判定には影響しません。
開発・運用のしやすさ
- 両サービスとも、接続プールが切れた接続を捨てて新しい接続を張るだけで復旧し、DSQL だけに必要な追加作業はありませんでした。DSQL は新しい接続ごとに IAM トークンが必要ですが、トークンを10分間キャッシュしたため再接続の遅延にはほとんど影響しませんでした。
- 測定ツールの不具合: D1 の最初の試行で、セル開始前に開いておいた管理用接続が遮断で切れ、セル後の整合性検査が失敗しました。セル終了後に新しい接続で検査するよう修正し、再測定しました。
費用
実行 B 全体の費用は E009 レポートの費用の節にまとめています。この試験は構成ごとに約3分の負荷でした。
結論と限界
- クライアント側の30秒の接続障害で、DSQL と A2 は同じ結果を示しました: 遮断区間のリクエストは失敗、解除直後に再接続、コミットの消失・重複0件。
- 限界: 1回の実行、小規模データ、低い負荷(300 TPS)です。今回の1回の実行で消失・重複がなかった結果を、絶対的な保証として一般化しません。DB のフェイルオーバーと DSQL 内部の障害は扱っていません。
後片付けの記録
- 実行 B で作成したリソース: BATCH(VPC、サブネット2つ、IGW、セキュリティグループ2つ、DB サブネットグループ、ランナーの IAM ロール・インスタンスプロファイル)、D1 DSQL クラスター、A2 クラスターと writer・reader、RDS 管理シークレット、Spot ランナー2台(D1
c6g.4xlarge、A2m7g.4xlarge)。E007 で AWS Backup ボールト、バックアップサービスロール、復旧ポイント2つ、復元した DSQL クラスター1つ、ポイントインタイム復元した A2 クラスターとインスタンスを追加で作成しました。 - 削除: バックアップボールトと復旧ポイント2つは 09:35 UTC に、復元した DSQL クラスターと A2 の復元先は 09:48 UTC から約 10:05 UTC にかけて、所有タグを確認したうえで削除しました。残りは
e002.py batch-downで 10:04–10:20 UTC に削除しました。削除に失敗したリソースはありません。 - 検証(10:20:27 UTC):
e002.py verifyの結果はremaining_count=0です。手動のクロスチェックで AWS Backup ボールト0個、この実行の接頭辞を持つ RDS クラスター・IAM ロール0個、未処理の Spot リクエスト0件を確認しました。この時点で残っていた DSQL クラスター1つは、同時に実行中だった実行 A(E002・E003・E008・E012)のものです。