このページでは、ログとWALプロトコル、チェックポイント、障害の3種類とロールバック・ロールフォワード、バックアップの種類、RPOとRTOがわかります。
- 一言で言うと:
- DBMS(データベース管理システム)が、たくさんの人が同時に使っても、壊れても、データを正しく保つ仕組みと、速く動かす工夫の話
- 正しさの約束(ACID特性)、同時に使うときの交通整理(ロック、MVCC)、壊れたときの復旧(ログ、チェックポイント、ロールバック/ロールフォワード)、速さ(インデックス、オプティマイザ、チューニング)が出てくる
約束(トランザクション、ACID特性)→ 同時に使う(ロック、デッドロック、2相ロック、MVCC)→ 壊れたら戻す(ログ、WAL、チェックポイント、障害の3種類、バックアップ)→ 速く探す(インデックス、オプティマイザ)→ 速さを保つ(分割、再編成)
覚え方の軸
- 障害回復は「COMMIT済みは前へ(redo)、未COMMITは後ろへ(undo)」
- ロールフォワードは更新後情報でredo、ロールバックは更新前情報でundo
- システム障害はチェックポイントから両方、トランザクション障害はロールバックだけ、媒体障害はバックアップ+ログでロールフォワード
- ログは先に書く(WAL)
障害回復:壊れたら戻す(★)
- 障害の種類:
- データベースシステムの障害は、大きく分けて「システム障害、トランザクション障害、媒体障害」の3つ
- 障害回復:
- これらの障害からデータベースを復旧し、一貫性が保たれた元の状態に戻すこと
① DBMSの仕組み(バッファリング)
- バッファリング:
- DBMSは、ディスクの入出力効率を上げるため、データをメモリ上にバッファリングし、データの更新はバッファ内のデータに対して行う
- 「バッファに空きがなくなった」などのタイミングで、バッファの内容をデータファイル(データベース)へ書き出す
- バッファリングの問題:
- バッファの内容と、データベースの内容が一致しない(更新したのに、まだデータベースに反映されていない)データがありうる
- ブロック(ページ)単位:
- DBMSの読み書きは、データ単位ではなく、そのデータが含まれるブロック(ページ)単位で行う
2つの障害ケース(トランザクションT1:A=A−10、B=B+10。Aは80、Bは20)
| ケース | 問題になる場合 | 必要な処理 |
|---|---|---|
| ①バッファ上のAを更新した後、障害が発生 | Aの書き出しが行われていた場合、「Aは変わったが、Bは変わっていない」という不整合 | Aの値を元の値に書き戻す |
| ②バッファ上のA、Bを更新しCOMMITした後、障害が発生 | 書き出しが行われていない場合、DBは整合しているが、COMMIT済みなので耐久性を満たさない | AとBの更新を、データベースに反映させる |
② ログ(ログファイル)
- ログ(ジャーナル):
- 上のような処理をするには、更新処理の更新前の値と更新後の値が必要
- そこで、DBMSは、これらの値を「“更新”、トランザクションID、データ名、更新前の値、更新後の値」のような形式で時系列に記録する。これをログという
- 更新の情報のほか、トランザクションの開始やCOMMIT、異常終了などの情報も記録される
- T1のログのイメージ:
- [更新、T1、A、80、70]
- [更新、T1、B、20、30]
③ WALプロトコル
- WALプロトコル:
- ログもデータと同じく、メモリ上のログバッファに記録され、その後、WALプロトコルに従ってログファイルへ書き出される
- WALプロトコルは、「変更データをデータベースに書き出す前に、ログファイルへの書き出しを行う」というルール
- WALは「Write Ahead Log(先にログを書け)」の略
- WALの効果:
- システム障害が起きると、メモリ上のバッファの内容は消える
- でも、WALプロトコルに従ってログを先に書き出しておけば、undo(値の書き戻し)やredo(データベースへの反映)ができる
- WALの例え:
- 家計簿の清書(データベース)を書き直す前に、必ずメモ帳(ログ)に「何を何から何に変えたか」を書いておく。清書の途中で邪魔が入っても、メモを見ればやり直せる
④ システム障害からの回復
- システム障害:
- OSやDBMSのバグ、またはオペレータの誤操作によって、システムがダウンしてしまう障害
- 発生すると、その時点のすべてのトランザクションが異常終了し、メモリ上のバッファの内容が消える
- undo/redo方式:
- システム再起動のリスタート処理では、ログファイルを基に、undo/redo方式で障害回復を行う
- undo:
- COMMIT済み以外のトランザクションによる更新を、ログの更新前の値(更新前情報)を使って元の値に書き戻す処理
- redo:
- COMMIT済みのトランザクションによる更新内容をデータベースに反映させるため、更新後の値(更新後情報)を使ってデータベースを更新する処理
- 障害回復の方式の種類:
- undo/redo方式(undoとredoの両方を行う)
- no-undo/redo方式(undoを行わない)
- undo/no-redo方式(redoを行わない)
チェックポイントリスタート(チェックポイント法)
- undo/redo方式の問題:
- 最大でシステム起動時からのログが必要になり、回復処理にも多くの時間がかかる
- チェックポイント:
- DBMSが、データバッファとログバッファの内容を書き出すタイミング
- チェックポイントを設けると、それまでの更新内容がすべてデータベースに書き出される
- だから、DBMSリスタートの際は、チェックポイントから障害回復処理をすればよく、回復時間も短くて済む
- チェックポイントとCOMMITは非同期:
- トランザクションがCOMMITされても、データバッファの内容は書き出されない
- ログバッファの内容は、トランザクションのCOMMITまたはチェックポイントの発生で、ログファイルに書き出される
チェックポイント
| バッファ | 書き出し先 | 書き出すタイミング |
|---|---|---|
| データバッファ | データベース | チェックポイント発生時(変更のあったブロック(ページ)を書き出す) |
| ログバッファ | ログファイル | トランザクションのCOMMITとチェックポイント発生時 |
- チェックポイントで一緒に書き出すもの:
- 「その時点で実行中のトランザクションの情報」と「チェックポイント情報」
- チェックポイントが発生するとき:
- 「データベースバッファに空きがなくなったとき」、または「ログファイルが切り替わるとき」
- 出題傾向(試験):
- チェックポイントの時に行われる処理と、チェックポイントを設けた効果が問われる
- ウォームスタートとコールドスタート:
- チェックポイントリスタートは、ウォームスタートの一種
- ウォームスタートは、保持している情報を基に内容を復元する前処理を行って再開する方式
- コールドスタートは、初期状態に戻して(前処理なしで)再開する方式
- チェックポイントの例え:
- ゲームのセーブポイント。電源が落ちても、最初からではなく、最後のセーブポイントからやり直せばよい
チェックポイントリスタート処理(POINT)(★)
- ロールバック(後退復帰):
- 障害発生時点からチェックポイントまで、逆方向にログファイルを見ていき、COMMIT済み以外のトランザクションによる更新を、更新前情報でundoする
- チェックポイント時点で実行中だったトランザクションがあれば、その開始時点まで戻り、そのトランザクションの更新をundoする
- ロールフォワード(前進復帰):
- チェックポイントから正方向にログファイルを見ていき、COMMIT済みのトランザクションによる更新を、更新後情報でredoする
- ロールバックとロールフォワード:
- ロールバックは、undoしていき、データベースを更新前の状態に戻すこと
- ロールフォワードは、redoしていき、データベースを障害発生直前の状態に戻すこと
- 例:
- TR2(障害発生時点でCOMMITしていない)の更新はロールバックされる
- TR1とTR3(障害発生前にCOMMIT済み)の更新はロールフォワードされる
- 出題傾向(試験):
- ロールバックすべきトランザクションと、ロールフォワードすべきトランザクションが問われる
例題(障害回復の判定)
- 問題:
- チェックポイントの後にシステム障害が起きた。次のトランザクションは、それぞれどう処理されるか
- TR-a:チェックポイントより前に開始・COMMIT
- TR-b:チェックポイントより前に開始し、チェックポイントの後・障害の前にCOMMIT
- TR-c:チェックポイントより前に開始し、障害時点で未COMMIT
- TR-d:チェックポイントの後に開始し、障害の前にCOMMIT
- TR-e:チェックポイントの後に開始し、障害時点で未COMMIT
- 答え:
- TR-aは、何もしない(チェックポイントでデータベースに書き出し済み)
- TR-bは、ロールフォワード(COMMIT済み。チェックポイント後の更新をredo)
- TR-cは、ロールバック(未COMMIT。開始時点まで戻ってundo)
- TR-dは、ロールフォワード(COMMIT済み)
- TR-eは、ロールバック(未COMMIT)
- 判定のコツ:
- 「障害の時点でCOMMITしていたか」で、前へ(redo)か後ろへ(undo)かが決まる
- 「チェックポイント前に終わっていた」ものは、何もしなくてよい
⑤ トランザクション障害からの回復
- トランザクション障害:
- デッドロックによる強制終了や、プログラムのバグなどで、トランザクションが異常終了する障害
- 回復の仕方:
- ACID特性の原子性により、トランザクションの中で行った処理をすべて取り消す必要がある
- DBMSは、データバッファの内容を、ログバッファの更新前情報でロールバックする
- すでにデータが書き出されていた場合は、ログファイルの更新前情報でデータベースをロールバックする
- ROLLBACK文:
- トランザクション障害ではないが、トランザクション自身がROLLBACK文を発行して、中で行った処理をすべて取り消すこともできる
- セーブポイント:
- セーブポイントを設けておけば、そのセーブポイント以降の処理だけを取り消せる
⑥ 媒体障害からの回復
- 媒体障害:
- 記憶媒体の故障で、データが読み出せなくなったり、データが消えてしまったりする障害
- 回復に使うもの:
- バックアップファイルと、ログファイル(更新後情報)
- バックアップファイル:
- 障害に備えて、データベースの内容を定期的に別の媒体に保存(退避)したファイル
バックアップの種類(★)
| 種類 | 中身 |
|---|---|
| フルバックアップ | データベース全体(すべてのデータ)をバックアップする |
| 差分バックアップ | 直前のフルバックアップからの変更分だけをバックアップする |
| 増分バックアップ | 直前のフルバックアップまたは増分バックアップからの変更分だけをバックアップする |
媒体障害からの回復(POINT)(★)
- リストア:
- バックアップファイルを別媒体にリストアして、データベースをバックアップ取得時の状態に戻す
- 差分・増分の反映:
- 差分バックアップ方式や増分バックアップ方式なら、リストア後のデータベースにそれを反映させる
- ロールフォワード:
- バックアップ取得後にCOMMITしたすべてのトランザクションの更新処理をredoしていき、データベースを媒体障害発生直前の状態に戻す
- ログファイルのバックアップ:
- 通常、ログファイルは複数用意され、ログファイル1から順に書き込み、1が一杯になるとログファイル2に切り替える
- ログファイルのバックアップは、この切替えのタイミングで行う(アーカイブログ)
例題(差分と増分)
- 問題:
- 日曜日にフルバックアップを取り、月〜木曜日は毎日バックアップを取る。金曜日の朝に媒体障害が起きた。①差分バックアップ方式、②増分バックアップ方式で、リストアに使うバックアップはどれか
- 答え:
- ①差分は、日曜のフル + 木曜の差分だけ(木曜の差分に、月〜木の変更が全部入っている)
- ②増分は、日曜のフル + 月・火・水・木の増分すべて(それぞれ前日からの変更分しか入っていない)
- どちらの場合も、その後、ログ(更新後情報)でロールフォワードして、障害直前まで戻す
- 長所と短所:
- 差分は、日がたつほど毎日のバックアップが大きくなるが、復旧は速い(2つで済む)
- 増分は、毎日のバックアップは小さいが、復旧に手間がかかる(全部を順に当てる)
データ復旧の要件(RPOとRTO)
- RPO(Recovery Point Objective:目標復旧時点):
- システム再稼働時、障害発生前のどの時点の状態に復旧させるかの目標値
- データ損失の最大許容範囲を意味する
- RTO(Recovery Time Objective:目標復旧時間):
- 障害発生時、どのくらいの時間で、いつまでに復旧させるかの目標値
- 障害停止の最大許容時間を意味する
- RPOとRTOの例え:
- RPOは「最悪、何時間前までのデータなら失ってもよいか」(毎晩バックアップならRPOは最大24時間)
- RTOは「止まってから何時間で動かせばよいか」
混同しやすいペア
- システム障害 / トランザクション障害 / 媒体障害
- システム障害は、OS・DBMSのバグや誤操作でシステムがダウン(ログでundo/redo)
- トランザクション障害は、デッドロックやバグでトランザクションが異常終了(ロールバック)
- 媒体障害は、記憶媒体の故障(バックアップ+ログでロールフォワード)
- undo / redo
- undoは、更新前情報で元の値に書き戻す(COMMIT済み以外)
- redoは、更新後情報でデータベースに反映する(COMMIT済み)
- ロールバック(後退復帰) / ロールフォワード(前進復帰)
- ロールバックは、undoしていき、更新前の状態に戻す
- ロールフォワードは、redoしていき、障害発生直前の状態に戻す
- データバッファ / ログバッファ
- データバッファは、チェックポイントで書き出す(COMMITでは書き出さない)
- ログバッファは、COMMITとチェックポイントで書き出す
- ログ / WALプロトコル
- ログ(ジャーナル)は、更新前・更新後の値などを時系列に記録したもの
- WALプロトコルは、データベースより先にログを書き出すルール
- ウォームスタート / コールドスタート
- ウォームスタートは、保持している情報で復元してから再開する(チェックポイントリスタート)
- コールドスタートは、初期状態に戻して、前処理なしで再開する
- ROLLBACK文 / セーブポイント
- ROLLBACK文は、トランザクション内の処理をすべて取り消す
- セーブポイントを使うと、そのセーブポイント以降の処理だけを取り消せる
- フルバックアップ / 差分バックアップ / 増分バックアップ
- フルは、全体をバックアップする
- 差分は、直前のフルからの変更分(復旧はフル+最新の差分)
- 増分は、直前のフルまたは増分からの変更分(復旧はフル+すべての増分)
- RPO / RTO
- RPO(目標復旧時点)は、どの時点まで戻すか。データ損失の最大許容範囲
- RTO(目標復旧時間)は、どのくらいの時間で戻すか。停止の最大許容時間