OracleのREDOとUNDO(概要説明)

レコードをINSERTするとき、テーブルとUNDO情報はREDOに入れて、COMMITまたはその前に、REDOログとして保存される。
障害時にREDOログを利用してCOMMIT後のデータを復活可能です。

主にREDOとUNDOを比較しながら説明する。
(REDOログの動作を完全に説明していないので、ご了承ください。
その場合、REDOログバッファとREDOログファイルを理解し、LGWRがリカバリ情報をREDOログに書き込み、
DBWRとARCHとメッセージ通信などを把握する必要がある。)
REDO:操作毎の情報をREDOログに保存し、インスタンス障害(停電等)し、データがデータファイルに書き込まれていない場合、
DBリスタート時REDOログが必要となり、インスタンスリカバリ(クラッシュリカバリ)が行われる。
UNDO:データが変更された場合のコピーで、ROLLBACK時、コピーを使って上書きする。
REDO:全ての操作を記録し、リカバリに使用する。(Redo records all the database transaction used for recovery)
UNDO:一つ前の操作を記録し、ロールバックに使用する。(undo is used to store uncommitted data information used for rollback)
 
REDO:コミットしたトランザクションインスタンスを記録し、リカバリ時データファイルに書き込む。
UNDO:未コミットのトランザクションを記録する。
なぜREDO:毎回COMMITする場合、データの変更をオンラインREDOログファイルに書き込むが、データファイルに書き込むとは限らない。
COMMIT済みで、オンラインREDOログファイルにしか存在しないため、障害時REDOログファイルから取り出しデータファイルに適用する必要がある。
なぜUNDOOracleが正常稼動時、パフォーマンスを考慮し、メモリも余裕がない場合に、メモリを確保するため、
DBWRがユーザがまだCOMMITしていない変更ブロックをデータファイルに書き込んでしまうからである。
そのため、COMMITする前のデータを記録する必要がある。
 
UNDOもデータファイルの一種であり、dirty bufferがハードディスクに書き込んでいないかもしれないので、
まずREDOログ適用成功後、UNDOデータファイルが保証され、それからROLLBACKが可能である。

UNDOの目的はシステムを障害前の状態に戻すためであり、さらにREDOログを適用するのはシステムの完全性を保証するためである。
UNDOを行なって前の状態に戻さないと、REDOを適用する意味がない。(ROLLFORWARD)

なので、インスタンスリカバリ時いつも先にROLLFORWARDしてからROLLBACKを行っている。
UNDO:
ロールバックセグメントのデータはLRU方式で保存されている。
ロールバックレコード=
   ブロック情報(トランザクションで変更するブロックの番号)+トランザクションコミット前にブロックに保存したデータ。
ロールバックセグメント毎にOracleが一つの「トランザクションテーブル」をメンテし、
そのテーブルに当該ロールバックセグメント全てのロールバックレコードの関連トランザクション番号(トランザクションSCNとロールバックレコード)
REDOREDOログはセットの「チェンジベクタ(Change Vector)」のからなっている。
それぞれのチェンジベクタにトランザクションがブロックに対する修正が記録されている。
ユーザがCOMMITした場合、LGWRプロセスがすぐにコミット記録をREDOログに書き込み、
トランザクション関連するREDOデータを書き込む。
COMMIT:
コミット前の動作として、
1)SGAのロールバックバッファでトランザクションロールバックレコードを生成し、
ロールバックレコードにデータの原始版が保存されている。 
2)SGAのREDOログバッファでトランザクションREDO記録を生成し、
REDOログにデータブロックに対する変更とロールバックセグメントのブロック変更が記録され、
バッファ内のREDOログはCOMMITする前にファイルに書き込む可能性がある。
3)SGAのデータベースキャッシュでトランザクションがDBに対する変更が記録され、
これらもCOMMIT前にファイルに書き込む可能性がある。

コミット時の動作として:
1)内部トランザクションテーブルの変更がコミットされ、唯一のSCN記録が生成し内部トランザクションテーブルに記録し、
このトランザクションを識別する。
2)LGWRプロセスがSGAのREDOログバッファのREDOログデータをオンラインREDOログファイルに書き込み、
当該トランザクションのSCNも記録する。
3)Oracleプロセスがトランザクションで使用したレコードロックとテーブルロックを解除する。
4)Oraceがユーザにトランザクションコミット完了を知らせる。
5)Oracleが当該トランザクションに処理完了とマークする。
ROLLBACK
ロールバック時の作業として、
1)Oracleロールバックセグメントのロールバックレコードを使って、トランザクションの全てSQL文変更を撤回する。
2)Oracleプロセスがトランザクションで使用したレコードロックとテーブルロックを解除する。
3)Oraceがユーザにトランザクションロールバック完了を知らせる。
4)Oracleが当該トランザクションに処理完了とマークする。
例:
 insert into a(id) values(1);(redoログ)
このレコードをROLLBACKする必要があるとする。
ロールバック文はdelete from a where id = 1;(undo記録)

まずinsert into a(id) values(1);(redoログ)を行わないと
delete from a where id = 1;(undo記録)する意味がないでしょう

正常のリカバリは:
まずinsert into a(id) values(1);(redoログ)
それでdelete from a where id = 1;(undo記録)
システムはもとの状態に戻って、このレコードがなくなる。