全銀ネットで起きていたこと(No337)
2023年10月に全銀ネットというシステムで障害が発生し、一部の銀行で他行宛の振込みができないという事態となりました。
この事件で起きたことにについてはこのメルマガでも10月に書きました。
その後、全銀ネットは2023年11月30日に金融庁への報告を行い、翌12月1日に記者会見を開きました。
今回は、その記者会見の内容を基にこのインシデント(事件/事故)の裏側で何が起きていたかをお話します。
何が起きたのか?
事故が起きたのは、10月10日朝でした。
その直前の10月7~9日の三連休でシステムの一部(中継コンピュータ)をリニューアルしたばかりでした。
10月10日の朝から他行への送金(と他行からの送金)が行えなくなり、トータルでは500万件もの取引が行えなくなるという事態になりました。
その後、全銀ネット側の奮闘もあり、10月12日には事態を収束させることができたというものです。
トラブルの詳細については、以下のバックナンバーをご参照ください。
No329 全銀ネットで何が起きたのか?(2023年10月配信)
https://note.com/egao_it/n/n69a0404f8e98
当時から、新しい中継コンピュータの内部プログラムに問題があったと言われていましたが、12月1日の会見でその事情が詳しく報告されました。
直接原因はプログラマの誤解
今回のインシデントの直接原因は現行の「銀行データのメモリ展開用プログラム(以下、銀行データ展開プログラムと書きます)」の仕様を誤解し、間違った修正を行ったことでした。
銀行データ展開プログラムは、全金融機関(約1500行)を高速に検索するためのファイル(ロードファイル)を作成するためのものです。
高速検索したいデータは銀行データ以外にもあるとのことで、データ種別ごとに個別の展開プログラムが用意されています。
全ての展開プログラムは同じロードファイルに作成したデータを書き込みます。
中継コンピュータが起動すると、ロードファイルをメモリに展開し、各プログラムから参照できるようにします。
ここでロードファイルがメモリ上に展開されるというのがポイントです。
メモリ上のデータならデータベースサーバにアクセスするよりも桁違いに速く結果が得られます。
ですが、ロードファイルは一つです。
設計段階で、どのデータ用の展開領域がどこからどこまでかを厳密に決めなければなりません。
各展開用プログラムの設計担当者は展開するデータごとに必要サイズを計算し、他の設計担当者と共有しておかなければなりません。
通常は、ロードファイルのレイアウトを決める管理者を置き、各プログラムが必要なデータサイズを元に、どの展開用プログラムがどこに書き込んで良いのかを決め、その情報を開発チームの全員と共有します。
各プログラムは決められた場所以外には絶対にデータを書き込まないルールです。
もし、他の領域に書き込むと他の展開用プログラムが作ったデータを破壊するからです。
さて、銀行データ展開プログラムの設計担当者はここでプログラム仕様を誤解してしまいます。その結果、必要な領域を増やす必要があるにも関わらず、今まで通りの容量で申告をしてしまった(過少申告)のです。
その結果、ロードファイルの作成時に、必要な領域の一部(末尾の2%程度)が他の展開プログラムによって上書き更新されました。
ここまでは、中継コンピュータのリニューアルの際(10月7~9日)に行われたのですが、この時点ではロードファイルを利用したテストで末尾の2%を利用するテストがなかったため、見過ごされてしまいます。
10月10日の朝に本番稼動した時、振込処理プログラムが銀行データを検索しようとして、末尾の2%部分にアクセスすると、想定外のデータに出くわします。
実際には、これは他の展開プログラムが上書きしたデータなのですが、振込処理プログラムはそんな事情は知りませんから処理が継続できずに異常終了した、というのが今回の経緯でした。
検出は不可能なのか?
だからといって、バグの検出ができないわけではありません。
システム開発は人間の行為ですから、誤解はどうしてもついて回ります。
こういった誤解をつぶすために、テストやレビューといった技法を用います。
テストとレビューについては、2023年5月の記事をご覧ください。
No307 システム開発でのテストとレビュー
https://note.com/egao_it/n/nb56e1bd1a757
通常であれば、今回のような不具合(バグ)は、どこかの段階で発見できるはずです。
1. 設計段階(設計書レビュー)
2. プログラミング(コーディング)段階(コードレビュー)
3. 単体テスト段階(テスト実施)
4. 結合テスト/総合テスト段階(テスト実施)
どうして、今回はその全てをすりぬけてしまったのでしょうか?
設計/プログラミング時に検出できたか?
今回のバグについて、各段階での検出可能性について考えてみます。
まずは、設計段階とプログラミング段階に着目します。
まず、最初の設計段階です。
本来はここで当システム経験者によるレビューが行われるべきでした。
このプログラムでは現場判断で設計レビューは不要と判断したようです。
ですが、この判断こそが痛恨のミスだと筆者は考えます。
確かに、プログラムの改修量はわずか(データサイズの変更)で、アルゴリズム(処理手順)の修正もないとなると、レビューは省略してもOK、という判断もあながち間違いではありません。
ですが、これを「システム全体の整合性」という視点で見ると答えが違ってきます。
上述の通り、このプログラムはロードファイルという一歩間違うと他プログラムのデータを破壊しかねない危険性を包んだ処理を実行します。
こう考えると、修正量の多寡にかかわらずシステム全体を見通す視点や経験を持つ人によるレビューが必要だ、という結論にならざるを得ません。
このプログラムが必要な領域を過不足なく確保していること、他の展開プログラムの領域を誤って上書きしないこと、といった視点でレビューを行うことは、決して無駄な行為ではなかったはずです。
後講釈に過ぎませんが、これを現場判断でスキップしてしまった点、そういった判断を許す体制であった点は大いに反省すべきです。
次にプログラミング段階です。
プログラミングレビュー(コードレビュー)でこのバグに気付いくのは難しそうです。
というのは、このプログラム自体は意図通りに動作するからです。
上述の通り、後続のプログラムがロードファイルの領域を上書きすることが問題ですので、このプログラムの内部処理を丁寧にレビューしても発見できません。
テストでバグを検出する難しさ
一般的にバグの検出はテストで行うケースが多いのですが、今回のような一部データの破損といったバグはテストで検出することは困難です。
三つ目は単体テスト段階です。
単体テストというのは、そのプログラムを実行し、結果(この場合はロードファイルの内容)が正しいことを確認します。
ここでは、プログラムそのものは正しいのです。ですから、作成したデータをいくら丁寧にチェックしてもバグは検出できません。
後続のプログラムによってデータ領域が上書きされれば気付くかもしれません。
ですが、単体テストは「単体」でのテストなのですから、後続のプログラムを動かすことはありません。
最後に、結合テスト/総合テスト段階です。
結合テストというのはテスト対象のプログラムと関係があるプログラムも合わせて(結合して)行うテストを言います。
また、総合テスト(システムテスト)は本番さながらに全プログラムを使って行うテストを言います。
結合テスト/総合テストは、単体テスト後に行いますので、各プログラムが正しく動くことは検証済です。
それでも、プログラム関の通信方法の食い違っている、後続プログラムが必要とするデータが揃っていない、といった単体テストでは見つからないバグが見つかりますので、結合テスト/総合テストは欠かすわけにはいきません。
特に総合テストはバグを見つけ出す最後の砦です。
この段階では、全プログラムが意図通りに連携して動くことを確認するのが目的です。
単体プログラムの動作確認は最少限とし、複数プログラムの組み合わせテストを主体とします。
また、組み合わせと言っても、全パターンをテストすると膨大な時間とコストがかかりますので、代表値をピックアップしてテストします。
上でも書いたように、今回破損していたのはインデックス領域のわずか2%に過ぎません。
代表値をピックアップして行う結合テスト/総合テストでこれを見つけるには相当の強運が必要です。
どうすればよかったのか?
上述の通り、設計段階でのレビューを省略してしまったことが悔まれます。
ここでシステム経験者によるレビューが行われていれば、最初の領域を増やさなくてもOKという判断に疑問を持つはずです。
となれば、設計者に「ホントに増やさなくてOKか?」と根拠を確認し、誤解に気付くことができたはずです。
レビューには30分もかからなかったと思います。
システム開発では常に「バグは早い段階で発見すればするほど影響が少ない」と言われます。
実際、今回のトラブルでは全銀側も開発担当のNTTデータ側もとてつもない費用負担をしています。
これが「30分のレビューをケチった結果」です。
バグを初期段階で見つけることの大切さを改めて感じます。
まとめ
2023年10月に発生した全銀ネットの障害に対する報告が行われました。
それによると、本インシデントの仕様誤解により必要な領域を確保できていなかったことが原因でした。
そのため、その領域にアクセスした振込処理プログラムが想定外のデータに出食わすことになり、結果として異常終了に至ったということでした。
このような誤解はプログラマであれば、誰もが経験することです。
だからこそ、他のメンバや経験豊かなメンバのレビュー(チェック)を受けることが重要です。
レビューとは、書き方や文言のチェックではありません。
矛盾がないか?その実現方法に問題はないか?他のプログラムと整合が保たれているか?目的を満たしているか?といった内容のチェックが対象です。
レビューを行うことは、経験の浅いメンバには先輩の失敗の擬似体験ができますし、経験のあるメンバにとってもは若手へのノウハウの伝え方の訓練になります。
また、今回はデータ領域のわずか2%の領域不足によるトラブルでしたので、大半のケースでは問題なく処理ができてしまいますので、テストで検出することもかなり難しそうです。
開発元では、レビューの強化に加えて、テスト実施時には代表値によるピックアップだけでなく一番良く使われている取引先などの項目を加えるといった対策を取るとのことです。
システム開発の難しさを改めて感じるインシデントでした。
今回は、全銀ネットの最終報告の内容についてお話しました。
次回もお楽しみに。
(本稿は 2023年12月に作成しました)
この記事が気に入ったらサポートをしてみませんか?