はじめに
システム開発をしていると、しょうもないことが原因で障害につながることがあります。本記事では、私が担当する業務でこの1年間で経験した障害事例とその対応、そして「こうしておけばよかった」という改善点を共有します。
同じような障害を未然に防ぐための参考になれば幸いです。
1. データベース移行試験時のデータ消失事故
背景
データベースの移行計画の一環として、新規DBの性能試験を実施。本番環境で一部のアプリケーションサーバをロードバランサから切り離し、性能試験を行った。
起こったこと
性能試験後、新規DBのデータをクリアしたが、別システムから当該実際には別システムがアプリケーションサーバのIP(RIP)に直接リクエストを送っていたため、試験後の新規DB削除により登録されたデータが消失。
影響範囲
- 一部のリクエストデータが失われ、復旧不可。
こうしておけばよかった
- 設定で変更可能なため、アプリケーションのリクエスト受付ポートを変更して性能試験以外のリクエストを受け付けられないようにする。
- データクリア前にログのgrepや簡単なクエリで、試験以外のリクエストが混入していないかを確認する。
2. バッチ処理の期待完了時刻の設定ミス
背景
外部システムからのバッチ処理リクエストをファイル経由で受け付ける仕組みで、一部のシステムに事情があり、バッチ処理に必要な処理完了期待時刻のパラメータを指定できなかったため、そのようなファイルは当該項目を受信側で埋め込むような処理を追加。
起こったこと
当日の18:00を期待完了時刻として付与するようにしたが、フロントシステムの処理遅延で18:00以降にファイルが連携されることがあり、ファイルを受信した時刻と完了期待時刻が逆転しエラーが発生。
影響範囲
- 一部のバッチ処理がエラーで停止。
- 後続処理にも影響。
対応
- 完了時刻が現在時刻以降になるように影響範囲のファイルを手作業で修正し、取り込み。
- 恒久対応として、ファイルの到着時刻が遅れる可能性を考慮し、期待完了時刻の設定ルールを見直し再リリース。
こうしておけばよかった
- 事前にファイル連携のタイミングを確認
3. ALTER TABLE によるシステムダウン
背景
PostgreSQLのテーブルにカラムを追加する ALTER TABLE を実施。
起こったこと
当該テーブルは大量のレコードを保持し、主要なトランザクションの多くで参照されるテーブルだった。長期間のテーブルロックが発生し、APIのレスポンスがタイムアウト。その結果、フロントのリトライ処理によりDBコネクション数が高騰し、システム全体がダウン。
(PostgreSQLではALTER TABLEを行う際にテーブルロックがかかり、そのテーブルの読み取り、更新SQLはALTER TABLEの完了を待ってから処理される知見はあったものの、ALTER TABLEにかかる処理時間を見誤っていて、障害に発展。)
影響範囲
- フロントからのリクエストがほぼ全てタイムアウト。
- システム全体の処理に影響。
対応
- 失敗した非同期処理は可能な限りリカバリ。
- 影響範囲をフロントシステムに共有し、必要に応じて再送依頼。
- 以後、テーブル定義変更時の影響を事前に検討するルールを策定。
こうしておけばよかった
- (私が担当するシステムは24/365システムなので現実的ではないところもありますが、)大量レコードを持つテーブルにALTER TABLE が必要な場合はシステム全断によるメンテナンスを検討する。
- テーブル設計時点でカラム追加が不要なデータの持ち方を検討するべきだった。
4. 誤ったデータパッチ適用によるエラー
背景
業務改善に伴い、特定のレコードのデータ形式を変更する必要があったが、対象のレコードは自システム内では判別できず、外部システムに依頼し、対象レコードのIDを抽出してもらいデータパッチを適用。
起こったこと
抽出作業のミスで不要なレコードまで変更され、オンライン処理でエラーが発生。
影響範囲
- 一部オンライン処理がエラーで停止。
対応
- パッチを切り戻し。
- 影響データを抽出し、失敗した処理はリカバリ、またはフロントに再送依頼。
- 対象となるデータを再抽出してもらい、後述する検証プロセスを追加したうえでパッチを再実施。
こうしておけばよかった
- (確実な方法ではないものの)データパッチ対象はこちらでは抽出できないものの、確実にパッチしてはいけないデータはこちらで出すことはできたため、突合せによる検証を行うことでパッチしてはいけないデータへのパッチを防げた。
5. SimpleDateFormat のフォーマットミス
背景
非同期処理の結果を返却するAPIを提供し、その応答項目に処理が完了した時刻を返却。
起こったこと
当該項目の日付から文字列への整形をJavaの SimpleDateFormatで行っていましたが、API仕様上 yyyyMMddHHmmss
を指定すべきだったところ、誤って yyyyMMddhhmmss
を指定してしまい、午前・午後の区別がつかなくなるバグが発生。
影響範囲
- APIのレスポンスで時刻情報が誤った形で表示。
対応策
- フォーマットを修正し再リリース。
こうしておけばよかった
- 13時以降のデータを含めたテストケースを用意するべきだった。
- 日付フォーマットは定数化し、実装者が個別に設定しないようにするべきだった。
まとめ
本記事で紹介した障害は、後から考えれば、障害が起こる可能性があったにもかかわらずそのリスクを見誤っていたものばかりでした。非常にバカバカしく、起こると悲惨な障害の種はどこにでも潜んでいます。この記事をご覧の皆さんは、私の失敗を笑っていただいてもいいので、同じようなミスから発生する障害を避けていただけたら幸いです。