学習・技術検証用デモ — 本システムは実際の銀行サービスではありません。

公開情報をもとに構築した教育目的のシステムです。実在する個人情報・口座情報・機密情報・認証情報等を入力しないでください。

ミニ銀行ACADEMY SYSTEM LEARNING
教材メニュー
学習進捗0 / 134
あと134項目
ADVANCED · 発展COURSE 09 · BANKING ENGINEERING

銀行エンジニアリング 32:障害に備える(書込停止・旧 writer・RTO と RPO)

主系が壊れたとき、バックアップから戻すだけでは足りません。古い側がまだ書いていないか、どこまで失ったか、いつ戻れるかを、先に決めておく必要があります。MiniBank v17の仕組みで確かめます。

41 / 55
BANKING ENGINEERING · 銀行エンジニアリング

v8以降に実装した台帳・記帳エンジンなどを実際に動かし、正常時と異常時の両方から銀行システムの構造を学ぶ。

Prerequisite: BANKING SYSTEM

LEARNING GOALS

このページで学ぶこと

  • RTO と RPO の測り方と、その限界
  • 書込停止(fence)と、旧 writer を止める書込世代
  • 復旧の状態と、二者確認による再開

PLAIN LANGUAGE

まず、ここだけつかむ

1

障害のときは、どこまで失ったか(RPO)、いつ戻れるか(RTO)、古い側がまだ書いていないかを、先に決めておきます。

2

書込停止(fence)は、営業日のゲートと同じ場所で、お金の動く書込みを止めます。再開は、レビューを出した人とは別の管理責任者が確認します。

3

書込世代(epoch)が再開のたびに上がり、古い設定のアプリの書込みを断ります。

DIFFICULT PARTS, STEP BY STEP

難しいポイントを、順番にほどく

専門用語を覚えることより、「なぜ必要か」「このシステムのどこで使うか」を理解することが目標です。

01

RTO/RPO

やさしく言うと

元どおり使えるまでの時間/失ってよいデータの範囲です。

なぜ必要?

復旧の目標を、数字で話せるようにするためです。

Minibankでは

演習で測った値と条件を recovery.drills に保存。目標や保証ではない。

02

書込停止(fence)

やさしく言うと

お金の動く書込みと、業務の状態を変える書込み(金額が 0 円のものも)を止めることです。

なぜ必要?

復元やの確認の最中に、古い側や別の処理が書き込まないようにするためです。

Minibankでは

ops.require_business_day_open に足した検査。RY001。

03

書込世代(epoch)

やさしく言うと

再開のたびに1つ上がる番号です。

なぜ必要?

古い設定のまま生き残ったアプリの書込みを見分けるためです。

Minibankでは

X-Writer-Epoch ヘッダーと MINIBANK_WRITER_EPOCH。不一致は RY002。

Level 1 基礎:障害のときに困る3つのこと

データベースが壊れて、バックアップから戻すことを考えます。困ることは3つあります。

①バックアップのあとに確定した取引は、戻したデータには無い(どこまで失ったか=RPO)。②壊れたと思った古い側が、実は動いていて書き続けている(二重運用)。③戻すのに時間がかかる(どれだけ止まるか=RTO)。

  • どちらも『この機械・このデータ量・この手順で測った値』です。目標値でも保証値でもありません。測るときは、データ量や機械の条件を一緒に残します。
用語意味MiniBankでの測り方
RPOどれだけ前の状態まで戻ってしまうか復元先の最後の仕訳の時刻と、顧客に成功と答えた最後の取引の時刻の差、そして失われた取引の数
RTO元どおり使えるまでにかかる時間書込停止を宣言してから、二者確認で再開するまでの時間(演習では人の待ち時間を0とするので、技術的な下限)

Level 2 銀行業務:復旧の状態と、書ける状態

状態は決められた順序でしか進みません。停止 → 復元 → 照合 → レビューの提出 → 別の管理責任者が再開。復元しない予防的な停止では、復元の段階を飛ばせます。各遷移には理由が必要で、追記専用の履歴に残ります。

状態意味お金の動く書込み
RUNNING/OPEN通常運転/復旧後に再開できる
FENCED書込停止(fence)できない(RY001)
RESTORINGバックアップから復元したできない
RECONCILING照合中できない
REVIEW二者確認待ちできない

Level 3 システム:MiniBankでの実装

  • 金融の書込みはすべて、15の表に付いた営業日のゲート(ops.require_business_day_open)を通る。v17はこのゲートに、復旧の状態の検査を営業日の判定の前に足した。新しい入口を作らないので、あとから追加した機能も自動で止まる
  • fence は EOD と同じ排他の advisory lock(74821,1)を取る。すでに走っている書込みが終わるのを待ち、その後ろに並んだ書込みは RY001 で失敗する。確定した書込みと止まった書込みの境目が明確になる
  • 書込世代(epoch)は再開のたびに上がる(外に控えた『それまでに発行した最大の世代』の1つ上。復元先が覚えている古い世代へは戻らない)。enforce_epoch を有効にすると、X-Writer-Epoch ヘッダー(アプリの環境変数 MINIBANK_WRITER_EPOCH)が現在の世代と一致しない書込みを RY002 で断る。古い設定のまま生き残ったアプリが書けなくなる
  • 再開(confirm_reopen)は、レビューを提出した人とは別の管理責任者だけ(RY005)。提出と再開には、最新の検証で manifest との比較を除く全項目が OK であること(RY004)、復元を経ている場合は、その間にバックアップの記録(manifest)との比較まで OK になった検証があることが必要
  • ゲートの表に載らない書込み(他行送金の送信、決済バッチ、営業日の開始・終了)にも、書込停止と書込世代だけを見る検査を付けた(recovery.require_writable)。決済バッチは、書込停止中に『一部失敗』として記録せず、RY001 で止まる
  • 復元を始める(begin_restore)には、障害の前にデータベースの外へ控えた manifest の digest と、それまでに発行した最大の書込世代が要る(RY007)。digest は方式の版つきで、既定は現行の 3。旧方式(2=group 等まで、1=元帳・口座・イベントだけ)で控えた値は、その版を明示して渡す(版が違えば NG。安全側)。運用者の一覧(external_operators)も、任意で渡せる。画面は、復元されたデータベースの中の値を入力の既定値にしない(それが外に控える意味を消すため)。提出者は自分の提出を差し戻せない(RY005)
  • 入力を間違えたまま詰まらないよう、復元中・照合中・レビュー中は abort_restore(復元のやり直し)で書込停止に戻せる。検証を省くものではなく、最初の宣言からやり直し、検証・提出・別の人の再開を通る
  • 運用者の権限(admin.admin_operators)は、digest に入れない。書込停止中でも運用者の『無効化』だけは許す(事故対応)ので、権限を digest に入れると、正当な無効化のせいで再開が詰まる。代わりに、障害の前に運用者の一覧(user_id・role・status。画面の『運用者の一覧(外に控える用)』。1〜500 件の配列)を外に控え、復元の宣言で渡す。復元後の検証(EXTERNAL_OPERATORS)は、一覧にある人の権限が一覧より『増えて』いたら NG にする(無効のはずが有効、運用者のはずが管理責任者)。減る向き(無効化)と、一覧にない人は NG にしない(一覧にない有効な運用者の人数 unlisted_active は、情報として出すだけ)。一覧を渡さなかったときは検査が走らず、検証に『検査せず』(declared:false)と出る。一方向の検査であり、外に控えた一覧を渡さなければ何も守らない
  • 遷移の履歴(recovery.transitions)は追記専用。更新や削除は PF001 で拒否される
  • 書込停止の間も、読取りと管理画面の閲覧はできる。許される書込みは、復旧の制御と検証、監査の記録、観測の記録(risk/twin のスナップショットと実行)、Open Banking の利用時刻の記録、再開時のトークン失効、運用者の無効化(事故対応)など。金額が 0 円でも、融資・価格・Open Banking・リスク/Twin の設定・日次の締め・運用者の権限(無効化以外)・KYC の状態など、業務の状態を変える書込みの多くは RY001 で止まる。ただし、AML のケース、調査、通知、清算の記録など、止めていない領域もある(V20-FREEZE-HARDENING.md の一覧)

異常時:古いアプリが、復旧後も書こうとする

段階内容
症状復旧の後に、古い設定のアプリからの書込みが RY002 で断られている(画面には『古い設定のまま動いている』と出る)
原因アプリの環境変数 MINIBANK_WRITER_EPOCH が、復旧前の世代のまま
確認管理画面『復旧・DR』の書込世代と、アプリの設定を照らし合わせる
対応アプリの設定を現在の世代にして再デプロイする。DB側の enforce_epoch を無効にして通すことは、原因が分かるまで避ける

Level 4 アーキテクチャ:フェンシング・トークン

古い書き手を止める定番の方法が、単調に増える番号(フェンシング・トークン)です。書き込む側が自分の世代を示し、受ける側が古い世代を断ります。MiniBankの世代はアプリの自己申告で、悪意のある書き手を防ぐものではありません(それは認証と権限の役割です)。防ぐのは『自分たちの古い設定のアプリ』です。

どこを確認すればよいか

  • 管理画面『復旧・DR』:状態、世代、履歴、検証、演習の記録
  • 運用センター:書込停止中は Recovery が赤になり、『書込停止中』の例外が出る

CHECK YOUR UNDERSTANDING

3問で理解チェック

答えを頭の中で考えてから、各項目を開いて確認してください。

Q1書込停止の間、顧客の残高の照会はできますか?
答え

できます。止めるのは、お金の動く書込みと、融資・価格・Open Banking・リスク/Twin の設定など業務の状態を変える書込みです(金額が 0 円でも止めます)。照会(読取り)は止めません。

Q2レビューを提出した人が、再開を確認できますか?
答え

できません。別の管理責任者だけです(RY005)。

Q3復旧の後に古い世代のアプリが書こうとすると?
答え

RY002で断られます。アプリの設定を現在の世代にします。

ここまで読めましたか?

完全に暗記する必要はありません。大切な考え方を説明できそうなら押してください。

SOURCE TRAIL

根拠と関連教材

CURRENT IMPLEMENTATIONは確認したrepository内の実装です。HISTORICAL IMPLEMENTATIONは導入・修正の履歴で、後続migrationによる再定義があり得ます。RELATED LESSONは教材への案内で、実装の一次Sourceではありません。ASSUMPTIONは仮定、UNKNOWNは未確認を表します。

確認基点: d02eae8914f39cbf06bfe422dc39c71886f82b3e / 2026-09-11。稼働環境への適用確認: UNKNOWN。パス実在の自動検査と、記述した技術的事実の確認は別です。

Implementation Status: IMPLEMENTED IN MINIBANK(この教材が扱うコードの範囲)

  • RELATED LESSON/docs/be-business-day-eod営業日のゲートと EOD の排他ロック
  • RELATED LESSON/docs/be-dr-restore-verify復元と検証
  • CURRENT IMPLEMENTATIONsupabase/migrations/20260930130000_v17_reliability.sqlops.require_business_day_open金融の書込みの共通のゲート。v17で、書込停止(RY001)と書込世代の不一致(RY002)を営業日の判定の前に追加
  • CURRENT IMPLEMENTATIONsupabase/migrations/20260930190000_v20_digest_v3_review.sqlrecovery.transition復旧の状態機械。遷移は管理責任者・理由つきで、追記専用に記録。再開は提出者とは別の管理責任者(RY005)。Freeze Hardening で、誤った宣言をやり直す abort_restore と、digest の方式の版を追加。digest 版 3 で、版は 1・2・3(既定 3)になり、外に控えた運用者の一覧(external_operators。任意)も受け取る。再監査で、一覧は 1〜500 件の配列だけを受け付け(空の配列は RY007)、保存するのは user_id・role・status の 3 つだけにした
  • CURRENT IMPLEMENTATIONsrc/app/admin/(protected)/recovery/page.tsxRecoveryPage()管理画面 復旧・DR(表示は RecoveryAdminView)
  • CURRENT IMPLEMENTATIONscripts/banking/v17-recovery.test.mjs状態機械・書込停止・書込世代・manifest と検証・トークン失効・訂正・演習記録のDBテスト