「昨日の何時に誰がこのデータを変更したのか調べたい」「意図せず削除されたレコードをどう特定するか」という場面で活躍するのがLogMiner(DBMS_LOGMNR)です。
LogMiner は Oracle の REDO ログ・アーカイブログを解析して、テーブルへの DML(INSERT・UPDATE・DELETE)の変更履歴を SQL 形式で取得します。監査・障害調査・誤操作の復旧に役立ちます。
この記事でわかること
- LogMiner の仕組みと必要な権限・設定
- DBMS_LOGMNR.ADD_LOGFILE でログファイルを追加する方法
- DBMS_LOGMNR.START_LOGMNR で解析を開始するオプション
- V$LOGMNR_CONTENTS で変更履歴を照会する方法
- サプリメンタルロギングを有効にして LogMiner の精度を高める方法
- LogMiner で取得できる UNDO SQL を使ったデータ復旧の考え方
必要な権限と事前設定
LogMiner の実行に必要な権限を確認する
-- LogMiner を実行するユーザーに必要な権限 -- ① EXECUTE ON DBMS_LOGMNR(ログ解析の実行) -- ② EXECUTE ON DBMS_LOGMNR_D(データディクショナリ操作) -- ③ SELECT ANY TRANSACTION(全トランザクションへのアクセス) -- ④ LOGMINING(Oracle 12c 以降、推奨) -- SYS または DBA が権限を付与する GRANT LOGMINING TO logminer_user; GRANT EXECUTE ON DBMS_LOGMNR TO logminer_user; GRANT EXECUTE ON DBMS_LOGMNR_D TO logminer_user; GRANT SELECT ANY TRANSACTION TO logminer_user; -- アーカイブモードが有効かどうかを確認する(LogMiner には推奨) ARCHIVE LOG LIST; -- ARCHIVELOG モードが望ましい(NOARCHIVELOG ではオンラインREDOログのみ解析可能) -- サプリメンタルロギングの状態を確認する SELECT log_mode, supplemental_log_data_min FROM V$DATABASE; -- SUPPLEMENTAL_LOG_DATA_MIN = YES → 最小サプリメンタルロギングが有効
サプリメンタルロギングを有効にする
通常の REDO ログは変更後の値のみを記録します。サプリメンタルロギングを有効にすると、変更前の値(BEFORE IMAGE)も記録されるようになり、LogMiner で UNDO SQL(変更前に戻す SQL)を取得できるようになります。
サプリメンタルロギングを有効にする
-- データベース全体の最小サプリメンタルロギングを有効にする
ALTER DATABASE ADD SUPPLEMENTAL LOG DATA;
-- これで LogMiner で ROW_ID が取得可能になる
-- すべての列の変更前値を記録する(完全サプリメンタルロギング)
ALTER DATABASE ADD SUPPLEMENTAL LOG DATA ALL COLUMNS;
-- 特定のテーブルのみ有効にする(推奨: 対象を絞る)
ALTER TABLE hr.employees ADD SUPPLEMENTAL LOG DATA ALL COLUMNS;
-- テーブルのサプリメンタルロギング設定を確認する
SELECT table_name,
log_group_name,
log_group_conditional,
always
FROM DBA_LOG_GROUP_COLUMNS
WHERE owner = 'HR'
ORDER BY table_name;
-- データベースレベルの設定を確認する
SELECT name, value FROM V$PARAMETER WHERE name LIKE 'enable_goldengate%';
LogMiner の基本的な使い方
STEP1: ログファイルを追加する(ADD_LOGFILE)
-- オンライン REDO ログのパスを確認する
SELECT member FROM V$LOGFILE ORDER BY group#;
-- アーカイブログのパスを確認する(期間指定)
SELECT name, first_time, next_time
FROM V$ARCHIVED_LOG
WHERE first_time >= TRUNC(SYSDATE) - 1 -- 昨日以降
AND standby_dest = 'NO'
ORDER BY sequence#;
-- LogMiner にログファイルを追加する
BEGIN
-- 最初のファイル: DBMS_LOGMNR.NEW で新規セッションとして追加
DBMS_LOGMNR.ADD_LOGFILE(
logfilename => '/u01/app/oracle/archivelog/arch_001.arc',
options => DBMS_LOGMNR.NEW
);
-- 追加ファイル: ADDFILE で続けて追加
DBMS_LOGMNR.ADD_LOGFILE(
logfilename => '/u01/app/oracle/archivelog/arch_002.arc',
options => DBMS_LOGMNR.ADDFILE
);
END;
/
STEP2: LogMiner セッションを開始する(START_LOGMNR)
-- LogMiner セッションを開始する
BEGIN
DBMS_LOGMNR.START_LOGMNR(
-- 解析時間範囲を指定する方法(ADD_LOGFILE でファイルを追加している場合)
starttime => SYSTIMESTAMP - INTERVAL '1' DAY, -- 1日前から
endtime => SYSTIMESTAMP, -- 現在まで
options =>
DBMS_LOGMNR.DICT_FROM_ONLINE_CATALOG -- データディクショナリの取得方法
+ DBMS_LOGMNR.COMMITTED_DATA_ONLY -- コミット済みデータのみ
+ DBMS_LOGMNR.SKIP_CORRUPTION -- 破損ブロックをスキップ
);
END;
/
-- オプションの説明:
-- DICT_FROM_ONLINE_CATALOG : オンラインカタログを使用(現在の定義で解析)
-- DICT_FROM_REDO_LOGS : ログ内のデータディクショナリを使用(過去の定義で解析)
-- COMMITTED_DATA_ONLY : コミット済みトランザクションのみ返す
-- NO_ROWID_IN_STMT : SQL 文に ROWID を含めない
-- DDL_DICT_TRACKING : DDL 変更もトラッキングする
STEP3: V$LOGMNR_CONTENTS で変更履歴を照会する
-- 特定テーブルへの DML 変更履歴を確認する
SELECT
timestamp, -- 変更のタイムスタンプ
seg_owner, -- テーブル所有者
seg_name, -- テーブル名
operation, -- INSERT / UPDATE / DELETE / DDL
username, -- 実行ユーザー
os_username, -- OS ユーザー名
sql_redo, -- 変更を再現する SQL(REDO)
sql_undo, -- 変更を取り消す SQL(UNDO)
row_id -- 対象行の ROWID
FROM V$LOGMNR_CONTENTS
WHERE seg_name = 'EMPLOYEES'
AND seg_owner = 'HR'
AND operation IN ('INSERT', 'UPDATE', 'DELETE')
ORDER BY timestamp;
-- 特定ユーザーの操作を抽出する
SELECT timestamp, operation, seg_name, sql_redo
FROM V$LOGMNR_CONTENTS
WHERE username = 'APP_USER'
AND operation != 'SELECT_FOR_UPDATE'
AND seg_owner NOT IN ('SYS', 'SYSTEM')
ORDER BY timestamp;
STEP4: LogMiner セッションを終了する
-- LogMiner セッションを終了する(SGA リソースを解放)
BEGIN
DBMS_LOGMNR.END_LOGMNR;
END;
/
UNDO SQL を使ったデータ復旧の考え方
削除されたレコードを UNDO SQL で復旧する(概念)
-- 誤って削除されたレコードの INSERT SQL を LogMiner から取得する例 SELECT sql_undo FROM V$LOGMNR_CONTENTS WHERE seg_name = 'EMPLOYEES' AND seg_owner = 'HR' AND operation = 'DELETE' AND timestamp >= SYSTIMESTAMP - INTERVAL '1' HOUR ORDER BY timestamp; -- sql_undo 列には "INSERT INTO HR.EMPLOYEES (col1, col2, ...) VALUES (...)" が含まれる -- この SQL を実行することで削除前の状態に戻せる -- 注意: UNDO SQL の実行前に必ずデータの整合性を確認すること -- ・外部キー制約・順序・トリガーの影響を検討する -- ・FLASHBACK 機能で対応できる場合は Flashback を優先する
LogMiner vs Flashback
・最近の変更を取り消すなら Flashback(AS OF TIMESTAMP / Flashback Table)が簡単
・アーカイブログの長期間の変更履歴を調査するなら LogMiner
・LogMiner は UNDO SQL を提供するだけで、自動的に変更を元に戻すわけではない
・最近の変更を取り消すなら Flashback(AS OF TIMESTAMP / Flashback Table)が簡単
・アーカイブログの長期間の変更履歴を調査するなら LogMiner
・LogMiner は UNDO SQL を提供するだけで、自動的に変更を元に戻すわけではない
まとめ
- ADD_LOGFILE → START_LOGMNR → V$LOGMNR_CONTENTS 照会 → END_LOGMNR が基本フロー
- COMMITTED_DATA_ONLY:コミット済みデータのみを返すオプション。通常はこれを指定する
- サプリメンタルロギング:`ALTER DATABASE ADD SUPPLEMENTAL LOG DATA` で有効化。UNDO SQL の精度が向上する
- sql_undo 列:変更を取り消す SQL が格納される。誤 DML の復旧に参照できる
- Flashback との使い分け:最近の変更は Flashback、長期間・詳細な調査は LogMiner を使う
Flashback を使ったデータ復旧は Flashback完全ガイドを参照してください。REDO ログの構造と管理は オンライン REDO ログ完全ガイドも参照してください。