rm /blog

IT系技術職のおっさんがIT技術とかライブとか日常とか雑多に語るブログです。* 本ブログに書かれている内容は個人の意見・感想であり、特定の組織に属するものではありません。/All opinions are my own.*

【障害記録】No.1:データ削除条件と画面表示(集計)条件不整合による計算不正

自分が体験したシステム障害を紹介してトラウマを抉り返す自虐コーナー
※特定避けるため一部脚色・変更しているが、大体ほぼ実体験。

障害No障害分類No
(自分用)発生分類
アプリ/データ/ミドル/ハード案件名個人的ヤバイ度
(5段階評価)

1 A アプリ データ削除条件と画面表示(集計)条件不整合による計算不正 ★★☆☆☆

 


 

 

発生日時 2017/07某日 解決日時 2017/07中 発見者 お客さん 対応者 原因者 俺ではない!(笑)
障害の詳細内容 とあるテーブルAがある。
テーブルAはユーザがアップロードしたデータファイルの物理名(絶対パス)やファイル容量を保持している。
テーブルAには「論理削除」と「物理削除」の2種類の削除が存在し、
100日で論理削除、
365日(1年)で物理削除している。

とある画面でテーブルAを参照して、
「過去アップロードした総容量」を計算して表示する箇所があった。
この「総容量」が、システムで規定した一定値と同値・ないし次のアップロードで超える場合、
ユーザからのアップロードを止める仕組みである。
が、
「総容量」の計算条件が365日になっていて、
過去1年分の全アップロードが容量計算の対象とされてしまった。


同画面内では明細単位で過去のアップロード記録を表示しているが、
こっちは論理削除条件を参照していて、
論理削除フラグ="0"のデータだけを取得していたため、
直近100日分のデータしか出てこない。
「総容量」の集計にも、一応「アップロード日時>=現在日時-365日」という条件がついてはいたが、
365日間レコードは物理的に存続しつづけるので、
論理削除条件がはいっていない以上、実質無条件と同じである。。

後で知ったが、100日間で40%に迫る使い方をしていたため(そんな使うモンだとは思ってなかった)、
365日だと余裕で100%を超える。
このテの問題の厄介なところはリリース後すぐには気付かれないところで、
大体120日目(4か月後)くらいに指摘があがってきている。
そのときは一気にでかいファイルをアップロードしたので余計に目立ったらしい…
このペースでは、普通に使っている分でも、
365日経過する前に容量不足に陥って業務停止に追い遣られたはずなので、
そう意味では直前になるまで気づかないよりは運が良かったともいえよう。。
対応内容・経緯等 最初問い合わせがあったときは、
システム不具合というよりは「容量上限を見直したい」という純粋な要望だった。
思ったより結構容量を食うから、容量上限を上方向に修正したいという意図だったらしい。
画面に表示されている明細の容量を足し合わせればそんなことはないとすぐ気付くのだが(明細は論理削除条件で見ているので)、
「容量」と「明細」をそれぞれ別個に表示しているため、
「容量」=「明細の足し合わせ」という固定観念が先行してしまい
システム不具合を疑いもしなかったようだ(これについては申し訳なく思っている)。

なかなか高頻度で使う業務機能であることもあり、
上記内容を素直にゲロって早期の対応を実施した。
⇒と、いいつつ、
 ユーザが実際生で利用してみたうえでの感想だったのか、
 「まあ、それはわかりました。対応をお願いします。
  しかしそもそもの話として、やっぱり容量上限は見直したい」

 という後続案件を引き出してしまったのが、この件の余罪となっている

修正にあたっては、論理削除条件を参照していない画面の集計条件の見直しを実施。
WHEREを一個加えるだけだ。
実装は簡単なのだが境界値テスト等を実施しなければならず、
テストデータの準備が思ったより面倒だった。

問合せがあってシステム不具合に事前に気付けたことから、業務影響が出る前に対応が出来たし、
この画面機能は特定ユーザ(特定の部署の方、ほぼ1人)しか使わず、
使い方も社内業務向けに特化した利用用途だったことから、
仮に業務影響が起きてもそこまでインパクトの大きい障害にはならなかっただろう。
反省点・あとがき 実日付ベースでは、比較的長い期間を通さないと判明しなかった問題ということもあり、
(しかもほとんど毎日継続的に利用していて初めて違和感に気付く)
テストでは見落としてしまっていたようだ。
テストにあたっても、
「バッチで消えてる中画面で見る」という連携的な確認も必要なのと、
設計書通りに実装はされていたので(要するに設計書の記述内容が既に誤っている)、
画面単体の検証で気付くのは難しかったのかもしれない。
フタを開けて横並びで整理してみると一目瞭然の単純な論理バグなのだが。

サーバにアプリが乗っかってしまうと、システム日付をいじくりまわすというのも
そう自由にできるわけでもないので、
工程が進むほどより発見は難しくなる。
とはいえ、ローカルの開発環境ならいくらでも日付を自由にできるわけだし、
もう少しコーディングやそれ以前の工程で事前検知はできたような気はする。
上述した通り、いわゆるありものの「設計書」だけではなく、
期間に着目した横並びの確認が、設計の段階で出来ていれば、
設計段階からこの問題を取り除くこともできたんだと思う。

ちなみに、この件には一つ「ぞっとする」余談が合る。
実際この件を修正対応するにあたって
社内で検討した結果以下2案が起案された。
  1. 夜間バッチによるテーブルAの物理削除条件を現状の365日から100日に短縮
  2. 画面で容量計算する際の条件を365日から100日に短縮

で、夜間バッチが割と汎用的なつくりをしている(日付関係の動的な条件が外だしされていて、比較的柔軟に書き換えやすい)ため
じゃあ夜間バッチ直すかって最初は倒れかけたのだが、
実際試しに直して動かしてみたらテーブルAが0件になったのである。
理由は、単に、その「外だし設定」に記述する日付の日数設定値を間違えただけなのだが、
実際バッチ処理「アップロード日時-(設定値)>=バッチ処理日」で削除するため、
(設定値)にあたる値は正の整数でいい。(365日前なら単に「365」とだけ設定すればいい)
が、勘違いして(バッチ処理をよく見ていなかったのも悪いが)「-365」と設定してしまったため、
テーブル内の全レコードが削除対象になってしまったのである。
正直最初は軽く対応するなら夜間バッチでいいやと思っていて
テストすらやる気が起きなかったくらいだが、
テストやっといてよかった~…と心底安心した。
これにトラウマを覚えて、1.が簡単とはいえ、なんかもうおっかなくて手を出す気が失せ、
2.の方針に転換して修正し、リリースした。