SQL技術

REDOとは古いデータを最新にし、UNDOとは最新データを古くする

[box class=”blue_box” title=”覚えるべきキーワード”]
・REDOログ
・REDOログバッファ
・アーカイブREDOログファイル
・リカバリ
・UNDOデータ
・読み取り一貫性
・ロールバック
[/box]

REDOとUNDOは良く似た言葉で、さらに使うシーンも似ているので混同してしまうエンジニアが多いように思います。(僕もその1人です)
読み取り一貫性はどっちだっけ?ロールバックはUNDO?ロールフォワードはREDO?など混乱してしまうんですね。でも、REDOとUNDOを逆にして覚えると、DB操作で大問題を引き起こすリスクが大です。データをぶっ壊してしまうかもしれませんので、しっかり区別して覚えるべきDBA用語トップ3に入ります。

一言でREDOとUNDOの違いとは?

REDOとUNDOの違いを一言で表すと、「REDOとは古いデータを最新にし、UNDOとは最新データを古くする。」記事タイトルのままですが、まさにこれです。REDOは、何らかの理由で古い状態になったデータを最新にし、UNDOは何らかの理由で新しくなってしまっているデータを古くします。

REDOの仕組み

そもそもREDOログの仕組みを考えてみましょう。ユーザーがデータを変更した時にREDOログ(変更履歴データ)がサーバープロセスによって生成されます。

REDOログが生成されるのは未コミットの状態です。さらにバッファキャッシュと呼ばれる共有メモリのデータが変更されます。(ディスクのデータではないことに注意) Oracleは最終的なデータ保存はディスク書き込みで実現しますが、ディスク書き込みは長い時間がかかるためバッファキャッシュにデータを保存しています。ですが、このバッファキャッシュは一時的な保存庫なので、たくさんのデータをキープしておくことができません。
全体の1/3がREDOログで満たされたときやコミットされたときに、バッファキャッシュのデータは吐き出され、即座にREDOログファイルに書きこまれます。そしてバッファキャッシュはすぐに新たなデータによって上書きされてしまいます。長い間、たくさんの更新データを入れておくことができません。一方、REDOログファイルは、バッファキャッシュよりもたくさんのデータが保存でき、簡単に上書きされません。REDOログファイルは常に多くの最新データで満たされています。REDOログファイルも順番が来れば上書きされますが、上書き前に一応、アーカイブREDOログファイルと呼ばれる新たなログファイルにREDOログファイルのデータが吐き出されるので、REDOログファイルとアーカイブREDOログがあれば、最新データが手に入ります。コミットされて、ディスクに書き込まれる一歩前に最新データはREDOログファイルに格納されるのがOracleの仕組みです。

インスタンスリカバリ

REDOログファイルを活用するシーンは主にリカバリ時です。電源が落ちたなどのインスタンス障害発生時はstartupコマンドで自動リカバリされますが、この時、障害発生時点のデータ状態に戻すためにREDOログファイルを使ってロールフォワードをします。REDOログファイルに格納されている最新情報を上書きするイメージです。

メディアリカバリ

データファイル破損などのメディアリカバリも同様で、REDOログファイルでロールフォワードを実行し、データを最新状態にします。

UNDOの仕組み

UNDOファイルもサーバープロセスによって生成されます。UNDOファイルはREDOログ生成と同じタイミングで生成されますが、コミットされるとデータはなくなります。(つまり、UNDOファイルに書かれているデータは未コミットデータとなります。)変更された未コミットデータを保存するファイル=UNDOファイルと思っていいでしょう。

UNDOは、最新データを古くするためにあると言いましたが、データベースのデータは古いデータよりも最新データの方がリアルタイムのデータなので正しいに決まっています。それなのに、なぜわざわざ古いデータに変換する必要があるのでしょうか。
ふるいデータを必要とするのは障害発生時です。一般的な操作で古いデータを必要とすることはありません。例えば、データ更新をして、未コミット状態の時に突然データファイルが破損してしまい、障害が発生したとします。REDOの段落で触れていますが、この場合、未コミット状態のデータはすでにREDOログファイルに書きこまれているので、REDOログファイルを使って、リカバリしたときには未コミット分のデータもバックアップされてしまいます。Oracleはコミットされたデータを絶対的に守る反面、未コミットデータは守らないという方針です。しかし、REDOログファイルにはコミットしたデータも未コミットしたデータも一緒に区別なく書きこまれているので、リカバリしたら未コミット分も反映されてしまいます。そのため、リカバリ後に未コミット分をロールバックする必要があります。さらに未コミット分の変更データのみ抽出したデータファイルも必要です。このファイルがUNDOファイルです。新しくなったデータに対して、UNDOデータを使い未コミット分のデータだけをロールバックします。

読み取り一貫性

AさんとBさんが同時にdptテーブルを操作していたとしましょう。
Aさんはselect * from dpt;を11時00に開始しましたが、deptテーブルには300万件のレコードが格納されているので、結果が表示されたのは11時12分でした。一方で、Bさんは11時3分にdept表に登録されている、name 列が‘asadaのage列を20から30に変更し、変更確認後にコミットをしました。(SQL:update dept set age = ‘30’ where name = ‘asada’;)
以上のような場合、Aさんの検索開始(11:00)~検索終了(11時12分)の間に変更されたname = ‘asada’のageは20になっているでしょうか、30になっているでしょうか。
答えは20です。Oracleは読み取り一貫性という仕組みがあって、これは検索処理に対してある時点のデータを見せる機能です。検索中にデータが変更されようとも検索開始時のデータを表示します。途中にデータが変更されていてもUNDOデータを使って、検索開始時点のデータを表示しています。

ロールバック

Oracleは未コミットでも、バッファキャッシュ上のデータは変更されています。ロールバック機能は、このバッファキャッシュの変更分をUNDOデータによって取り消す機能です。
ロールバックの裏側は変更されたバッファキャッシュのデータをUNDOデータによって元に戻しているのです。

一般的にエンジニアは、「コミットするまでデータは変更されない」と教わってきたと思いますが、実際のところ、裏ではコミット前でもデータ変更処理は発生しています。余分な誤解を生まないために、そのように説明されているに過ぎません。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です