[Oracle] LogMiner の使い方 | Archive Redo Blog

Archive Redo Blog

DBエンジニアのあれこれ備忘録

データベースの運用中、アプリケーションやユーザーの操作ミスにより、データの整合性に矛盾が生じてシステムが正常に動作しなくなるようなことがあります。

このような場合、いつ誰がどのような操作を行ったのかを追跡して原因を追求するわけですが、アプリケーションレベルのログなどの情報だけでは原因が特定できないことも多々あります。

しかし、アプリケーションレベルで原因を特定できない場合でも、データベースにデータ変更のログが残っており、それを追跡することができれば確実にどの時点でデータに不整合が発生したのかを特定することが可能です。

Oracleでは全てのデータの変更が REDOログファイルに記録されます。

これは本来障害発生時にデータのリカバリを行うためのものですが、LogMinerという機能を用いることによってこれをデータ分析用途で使用することが可能になります。

サプリメンタル・ロギングの設定
LogMinerで REDOログファイルを分析するためにはサプリメンタル・ロギングを有効にして、 REDOログファイルに追加情報を書き込む必要があります。

サプリメンタル・ロギングはデフォルトでは無効となっているため、LogMinerで REDOログファイルを分析する場合はあらかじめサプリメンタル・ロギングを有効にしておかなければなりません。

つまり、急に LogMinerで分析したいと思ってもできないわけです。

しかし、サプリメンタル・ロギングを有効にするとそれだけ REDOログに書き込まれる情報量が増えます。

サプリメンタル・ロギングには、最小限のロギングと識別キーによるロギングという 2つのタイプがあり、最小限のロギングであればパフォーマンスにはほとんど影響しないそうですが、注意が必要です。

最小限のロギングを有効にするには以下のコマンドを実行します。

ALTER DATABASE ADD SUPPLEMENTAL LOG DATA;

分析対象の REDOログファイルの指定
LogMinerで REDOログファイルを分析するには、まず分析対象の REDOログファイルを指定します。

EXECUTE SYS.DBMS_LOGMNR.ADD_LOGFILE(
  LOGFILENAME => 'C:\oracle\product\10.1.0\oradata\ORCL\REDO01.LOG',
  OPTIONS => SYS.DBMS_LOGMNR.NEW
);

LogMinerでは オンライン、アーカイブ、いずれの REDOログファイルでも同じように分析することが可能です。

分析対象のデータベースからコピーしてきた REDOログファイルを別のデータベース上で分析することも可能です。

また、複数の REDOログファイルを分析する場合は、以下のコマンドで追加します。

EXECUTE SYS.DBMS_LOGMNR.ADD_LOGFILE(
  LOGFILENAME => 'C:\oracle\product\10.1.0\oradata\ORCL\REDO02.LOG',
  OPTIONS => SYS.DBMS_LOGMNR.ADDFILE
);

分析の開始
分析対象の REDOログファイルを指定したら、以下のコマンドを実行して分析を開始します。

EXECUTE SYS.DBMS_LOGMNR.START_LOGMNR(
  OPTIONS => SYS.DBMS_LOGMNR.DICT_FROM_ONLINE_CATALOG + SYS.DBMS_LOGMNR.COMMITTED_DATA_ONLY
);

この時、様々なパラメータを指定することができますが、重要なのはディクショナリの指定です。

ディクショナリを指定すると、LogMinerは REDOログファイルの内容をユーザーが識別しやすいオブジェクト名や外部データ形式に変換してくれます。

分析対象の REDOログファイルをそのデータベース上で分析する場合は、オンライン・カタログを利用できますので、上記のように オプションに SYS.DBMS_LOGMNR.DICT_FROM_ONLINE_CATALOGを指定します。

別のデータベース上で分析する場合は、事前に分析対象のデータベース上でディクショナリを抽出しておく必要があります。

ディクショナリはフラットファイル、または REDOログに抽出することができますが、フラット・ファイルに抽出する場合は以下のコマンドを実行します。

EXECUTE SYS.DBMS_LOGMNR_D.BUILD(
  DICTIONARY_FILENAME => 'dictionary.ora', 
  DICTIONARY_LOCATION => 'C:\oracle\', 
  OPTIONS => SYS.DBMS_LOGMNR_D.STORE_IN_FLAT_FILE
);

フラットファイルに抽出したディクショナリを使用する場合、分析の開始時にディクショナリファイル名を指定します。

EXECUTE SYS.DBMS_LOGMNR.START_LOGMNR(
  OPTIONS => SYS.DBMS_LOGMNR.COMMITTED_DATA_ONLY, 
  DICTFILENAME => 'C:\ORACLE\dictionary.ora'
);

V$LOGMNR_CONTENTSの参照
分析対象の REDOログファイルの内容は V$LOGMNR_CONTENTS ビューに格納されますので、分析したい事象に応じた問い合わせを実行します。

例えば、SCOTTユーザーが行った INSERT、UPDATE、DELETE操作を参照したい場合は以下のような問い合わせを実行します。

SQL> SELECT
  2    SCN,
  3    TO_CHAR(TIMESTAMP,'YYYY/MM/DD HH24:MI:SS') AS TIMESTAMP,
  4    SQL_REDO
  5    FROM V$LOGMNR_CONTENTS
  6    WHERE USERNAME = 'SCOTT'
  7      AND OPERATION IN ('INSERT','UPDATE','DELETE')
  8    ORDER BY SCN;

       SCN TIMESTAMP            SQL_REDO
---------- -------------------- ----------------------------------------
   9741848 2008/01/21 11:39:51  insert into "SCOTT"."EMP"("EMPNO","ENAME
                                ","JOB","MGR","HIREDATE","SAL","COMM","D
                                EPTNO") values ('7000','WOODS','ENGINEER
                                ','7839',TO_DATE('07-01-01', 'RR-MM-DD')
                                ,'500',NULL,'40');

   9742262 2008/01/21 11:50:20  update "SCOTT"."EMP" set "ENAME" = 'WOOD
                                S' where "ENAME" = 'TIGER' and ROWID = '
                                AAAL+ZAAEAAAAAcAAA';

   9742275 2008/01/21 11:50:44  delete from "SCOTT"."EMP" where "EMPNO"
                                = '7000' and "ENAME" = 'WOODS' and "JOB"
                                 = 'ENGINEER' and "MGR" = '7839' and "HI
                                REDATE" = TO_DATE('07-01-01', 'RR-MM-DD'
                                ) and "SAL" = '500' and "COMM" IS NULL a
                                nd "DEPTNO" = '40' and ROWID = 'AAAL+ZAA
                                EAAAAAcAAA';

このようにいつ誰がどのような操作を行ったのかを追跡することができるわけです。

ただ、LogMinerを使用するにはサプリメンタル・ロギングを有効にしておかなければならないということになっていますが、Oracle10gでは確かにサプリメンタル・ロギングが無効のままだと DML文が表示されなかったのですが、9iではサプリメンタル・ロギングが無効のままでも DML文が表示されました。

どうもバージョンによって若干動作が異なるようです。

分析の終了
LogMinerによる分析を終了する場合、以下のコマンドを実行します。

EXECUTE SYS.DBMS_LOGMNR.END_LOGMNR();

参考:「Oracle Database ユーティリティ 10g リリース2」