はじめに
OracleデータベースのREDOログとUNDOログは、データベースのリカバリと整合性を維持するために重要な役割を果たします。
LogMinerを使用してREDOログとUNDOログ見てどのような内容か確認してみました。
REDOログ
REDOログは、RE(再)+DO(実行)で再実行用のログ。Oracleデータベースの変更操作を記録するログファイルで、データベースのクラッシュや障害が発生した場合に、データをリカバリするために使用される。
UNDOログ
UNDOログは、UN(しない)+DO(実行)で実行取り消し用のログ。トランザクションが行った変更を元に戻ので、トランザクションのロールバックやデータの一貫性を維持できる。
LogMiner
LogMinerは、LogMinerは、Oracleデータベースのツールの一つであり、REDOログファイルの内容を解析して、データベースに対する変更履歴を確認できる機能です。
解析準備
1. LogMinerのセットアップ
まず、Oracleデータベース内に新しいディレクトリオブジェクトを作成し、pudding_logmnr_dict.oraというLogMinerの辞書ファイルを作成します。LogMinerの辞書ファイルは、Oracleデータベースのメタデータ情報を含むファイルであり、REDOログファイルを解析する際に必要な情報が含まれます。なお、今回はプリン(英語ではpudding)を例に使用しています。「プリンは栄養たっぷりん。言うてな!」
CREATE OR REPLACE DIRECTORY logmnr_dir AS '/u01/app/oracle';
EXEC DBMS_LOGMNR_D.BUILD(dictionary_filename => 'pudding_logmnr_dict.ora', dictionary_location => 'LOGMNR_DIR');
2. サンプルテーブルの作成
次に、プリンに関連するサンプルテーブルを作成し、データを挿入します。
CREATE TABLE eiyou (
id NUMBER PRIMARY KEY,
name VARCHAR2(50)
);
INSERT INTO eiyou (id, name) VALUES (1, 'Purin');
INSERT INTO eiyou (id, name) VALUES (2, 'Pudding');
↓みたいな、ちょっとしたテーブルです。
3. LogMinerに解析対象のREDOログファイルを追加
DBMS_LOGMNR.ADD_LOGFILEプロシージャは、LogMinerに解析対象のREDOログファイルを追加するもので、それぞれのREDOを以下のコマンドで追加しています。
BEGIN
DBMS_LOGMNR.ADD_LOGFILE(
LOGFILENAME => '/u02/oradata/CDB1/redo03.log',
OPTIONS => DBMS_LOGMNR.NEW
);
DBMS_LOGMNR.ADD_LOGFILE(
LOGFILENAME => '/u02/oradata/CDB1/redo02.log',
OPTIONS => DBMS_LOGMNR.ADDFILE
);
DBMS_LOGMNR.ADD_LOGFILE(
LOGFILENAME => '/u02/oradata/CDB1/redo01.log',
OPTIONS => DBMS_LOGMNR.ADDFILE
);
END;
/
※補足:REDOのパスは以下のSQLコマンドで確認してます。
SELECT MEMBER FROM V$LOGFILE;
解析してみる
1. 解析の開始
以下のコマンドで解析を開始します。これは、LogMinerを起動してREDOログファイルの解析を開始するためのコマンドです。
EXEC DBMS_LOGMNR.START_LOGMNR(DictFileName => '/u01/app/oracle/pudding_logmnr_dict.ora');
2. REDOとUNDOの確認
V$LOGMNR_CONTENTSビューを使用してREDOとUNDOの中身を確認します。
最初の実行では正しく結果が表示されないことがあったので、2回実行しました。1回目に出力されなかった原因は調べても良く分からなく、内部的にキャッシュか何かがあるんだとうか。。。
2回目の実行は「EXEC DBMS_LOGMNR.END_LOGMNR;」を使用して1回解析を止めています。また、テーブル作成のSQLは実行してません。
SELECT
TO_CHAR(TIMESTAMP, 'YYYY-MM-DD HH24:MI:SS') AS TIMESTAMP,
SQL_REDO,
SQL_UNDO
FROM
V$LOGMNR_CONTENTS
WHERE
TABLE_NAME = 'EIYOU'
ORDER BY TIMESTAMP;
EXEC DBMS_LOGMNR.END_LOGMNR;
EXEC DBMS_LOGMNR_D.BUILD(dictionary_filename => 'pudding_logmnr_dict.ora', dictionary_location => 'LOGMNR_DIR');
BEGIN
DBMS_LOGMNR.ADD_LOGFILE(
LOGFILENAME => '/u02/oradata/CDB1/redo03.log',
OPTIONS => DBMS_LOGMNR.NEW
);
DBMS_LOGMNR.ADD_LOGFILE(
LOGFILENAME => '/u02/oradata/CDB1/redo02.log',
OPTIONS => DBMS_LOGMNR.ADDFILE
);
DBMS_LOGMNR.ADD_LOGFILE(
LOGFILENAME => '/u02/oradata/CDB1/redo01.log',
OPTIONS => DBMS_LOGMNR.ADDFILE
);
END;
/
EXEC DBMS_LOGMNR.START_LOGMNR(DictFileName => '/u01/app/oracle/pudding_logmnr_dict.ora');
SELECT
TO_CHAR(TIMESTAMP, 'YYYY-MM-DD HH24:MI:SS') AS TIMESTAMP,
SQL_REDO,
SQL_UNDO
FROM
V$LOGMNR_CONTENTS
WHERE
TABLE_NAME = 'EIYOU'
ORDER BY TIMESTAMP;
TIMEATAMP | SQL_REDO | SQL_UNSO |
---|---|---|
2024-07-21 10:00:36 | "CREATE TABLE eiyou ( id NUMBER PRIMARY KEY, name VARCHAR2(50));" | (null) |
2024-07-21 10:00:37 | insert into "SYS"."EIYOU"("ID","NAME") values ('2','Pudding 2'); | delete from "SYS"."EIYOU" where "ID" = '2' and "NAME" = 'Pudding 2' and ROWID = 'AAASF2AABAAAeXXXXXX'; |
2024-07-21 10:00:37 | insert into "SYS"."EIYOU"("ID","NAME") values ('1','Pudding 1'); | delete from "SYS"."EIYOU" where "ID" = '1' and "NAME" = 'Pudding 1' and ROWID = 'AAASF2AABAAAeXXXXXX'; |
3. 確認結果
REDOログには実行したINSERT文が記録され、UNDOログにはそれを取り消すDELETE文が記録されていました。
INSERTしか実行していなくても、自動的にUNDO用のコマンドが記録されています。
また、CREATE TABLEのようなDDL(データ定義言語)操作は、UNDO情報が生成されないです。UNDO情報は主にDML(データ操作言語)の例えばINSERT、UPDATE、DELETEなどで使用されるためです。
まとめ
LogMinerを使用することで、OracleデータベースのREDOログとUNDOログの中身を確認することができました。
うまく進まない箇所もありましたがディレクトリオブジェクトやプロシージャのあたりについても理解を深めることができ、実際に手を動かすことで有益な知識を得られたと思います。