Aurora RDSで発見された競合状態(race condition)の事例
(hightouch.com)- AWS Aurora RDS で発生した 競合状態バグ を実験的に確認し、AWSから原因の確認を得た事例
- Hightouchは イベント処理システムの拡張中、Auroraの failover(フェイルオーバー) 過程で書き込みインスタンスの切り替えに失敗する現象を発見
- ログ分析の結果、2つのインスタンスが同時に書き込み処理を実行し、ストレージ層の衝突とプロセス終了が発生したことを確認
- AWSは 内部シグナル処理の問題 により、以前の writer の降格が完了していない状態で新しい writer が昇格したことが原因だと正式に確認
- この事例は 大規模分散システムにおける並行性制御の重要性 と、障害対応時の 書き込み停止手順の必要性 を強調
背景
- 2025年10月20日、AWS
us-east-1リージョンで DNS管理システムの競合状態バグ による障害が発生 - Hightouchはこれにより イベント処理バックログ が急増し、システムの限界に到達
- 処理量を確保するため、10月23日に Aurora RDSインスタンスのアップグレード を実施し、この過程で新たな競合状態バグを発見
Hightouchイベントシステムの構成
- イベント収集と送信を担うシステムは Kubernetes、Kafka、Postgres(Aurora) で構成
- Postgresは バッチメタデータキュー として使われ、毎秒50万件のイベントを1秒以内に処理
- Aurora PostgreSQLは 書き込み専用(primary) インスタンス、読み取り専用(replica) インスタンス、そして 共有ストレージ層 で構成
アップグレード計画
- 読み取りインスタンス追加 → 既存リーダーのアップグレードと failover 優先順位の付与 → failover 実行 → 既存 writer のアップグレード → 一時的リーダーの削除
- この手順はAWSドキュメントに明記された方法であり、ステージング環境で負荷テストにより検証済みの手順 だった
アップグレード試行と問題発生
- 10月23日 16:39 EDT、failover 実行後に 既存 writer が再び primary に戻る 現象が発生
- 2回の試行はいずれも同じ結果で、書き込み不可エラー(DatabaseError: cannot execute UPDATE in a read-only transaction) が一部サービスで発生
- ログ分析の結果、2つのインスタンスが同時に書き込み処理を行い、ストレージ衝突により終了 したログを確認
競合状態の原因
- Aurora の failover 過程における ステップ3(既存 writer の降格) と ステップ4(新しい writer の昇格) の間で 競合状態が発生
- これにより2つのインスタンスが同時に書き込み権限を持ち、衝突
- 書き込みトラフィックを除いた状態で再試行すると failover が正常完了し、競合状態という仮説が立証 された
AWSの確認と対応
- AWSは内部レビューの結果、writer 降格シグナルの処理エラー が原因であり、Hightouchの設定やトラフィックパターンとは無関係だと確認
- 修正はロードマップに含まれており、暫定対応策として failover 中の書き込み停止 を推奨
最終対応
- Hightouchはクラスターのアップグレードを完了し、
- 意図的な failover 前に書き込みを停止する手順を追加
- writer 役割変更の監視モニタリングを強化
- 運用マニュアル(playbook)を更新 を実施
主な教訓
- 移行中の予期しない状態遷移 に備えた復旧準備が必要
- 可観測性(observability) の確保が問題検知の鍵
- 分散システム構成要素間の影響を最小化する設計 の重要性
- テスト環境と実運用環境の違い を認識する必要がある
原文に追加情報なし
1件のコメント
Hacker Newsの意見
この記事を見ると、手動フェイルオーバー中にもアプリケーションが通常どおり書き込みトラフィックを維持しようとすると、常に失敗するように見える
ただ、いくつか疑問がある。ほかのAuroraユーザーがなぜこの問題を常に経験していないのか、AWSが知らないはずはないのではないか、もし知っているならなぜP0級の緊急問題として扱わないのかが気になる
もしかすると、進行中のトランザクション状態やタイムアウトのような微妙な条件が作用しているのかもしれない
SELECT ... FOR UPDATEが静かに失敗し、トランザクションがautocommitモードに切り替わるバグに遭遇したことがある。誰も関心を示さず一人で騒いでいたが、数か月後に別の人から同じ問題を経験したと連絡が来た。結局修正はされたが、その頃にはもう関心を失っていた関連リンク: Stack Overflowの質問
Aurora PostgreSQLで予期しない動作を何度も見たことがある
特にZero Downtime Patching (ZDP)中にセッション状態が誤って保持され、単純なクエリでさえ
statement_timeoutよりはるかに早くキャンセルされる現象を経験した私の推測では、クライアントが再接続する際に、Auroraが前のセッションの古いタイマー状態をそのまま引き継ぎ、クエリが即座にキャンセルされているように思える
こちらも書き込みトラフィックが非常に高い環境で定期的にフェイルオーバーを実施しているが、AWS JDBC wrapperを使った自動化プロセスにより安定して運用できている
こうした基本的な不変条件をAuroraが維持してくれると信じてお金を払っているのに、こんな問題が起きるとは驚きだ
ログとAWSの説明を見る限り、元記事の著者の仮説は誤っているようだ
**昇格の失敗後、外部監視プロセスがクラスター状態の不一致を検知して強制終了(kill -9)**したように見える。ストレージサブシステム関連のメッセージはその後に発生したものだ
AuroraとRDS Postgresの性能比較について聞いてみたい
マルチAZや高速フェイルオーバーが不要なら、RDSでgp3 64k IOPS構成のほうがより高い性能を出せるだろうか。Auroraは特にinsert性能が遅く、コストが高いように見える。ベンチマークもRDS側の設定を明確に示していないことが多く、信頼しづらい
また、IOPSを自分でプロビジョニングする必要がなく、約80k IOPSが提供される。
IO課金方式にも2種類あり、pay-per-IOは低負荷環境向け、固定料金モードはIOの多いワークロード向けに有利だ。
ちなみにServerlessはほぼ常に割高だった。短時間のピークがある場合にだけ有用だ
AWSエンジニアが言う**「レゴブロックモデル」がよく表れている
ストレージ層を完全に独立して設計したことで、上位サービスが失敗してもデータ整合性**は保証された。AWSエンジニアリングの良い事例だと思う
AWSが「フェイルオーバー中は書き込みを止めろ」と勧告したというが、関連ケース番号を共有してもらえるだろうか
こうした問題を経験したのが自分だけではないとわかって安心した
Auroraのコンピュート・ストレージ分離アーキテクチャは興味深い
MSSQLのHyperscaleも似た構造で、Azureのサービスの中では実際に使ってみてもよいと思えるほぼ唯一の製品だ