Oracle LogMiner日志挖掘操作总结
2026/8/22 3:15:51 网站建设 项目流程

Oracle LogMiner日志挖掘操作总结


一、工具介绍

1.1 什么是LogMiner

Oracle LogMiner 是 Oracle 从 8i 版本开始提供的一个极其强大且免费的内置分析工具。它通过一组 PL/SQL 包(DBMS_LOGMNRDBMS_LOGMNR_D)和动态视图(如V$LOGMNR_CONTENTS),将 Oracle 重做日志(Online Redo Logs)和归档日志(Archived Logs)中晦涩难懂的底层二进制数据,转化为人类可读的 SQL 语句。

LogMiner工具既可以用来分析在线日志,也可以分析离线日志文件;既可以分析自身数据库的重做日志文件,也可以用来分析其他数据库的重做日志文件。

1.2 LogMiner的作用

LogMiner的四大作用:

场景说明
数据变更审计精准追踪DML操作(INSERT/UPDATE/DELETE)的执行时间、用户及影响范围
误操作数据恢复当发生错误的DELETEUPDATE且超出了 Flashback Query 的保留窗口时,通过提取SQL_UNDO语句进行精确回滚。
DDL 变更回溯找回被意外删除或修改的存储过程、表结构等元数据。
性能与容量分析分析哪些表在特定时间段内被频繁修改,为数据库调优和扩容提供历史依据

1.3 LogMiner的主要组件

LogMiner分析工具实际上是由一组PL/SQL包动态视图组成。

核心PL/SQL包

包名用途
DBMS_LOGMNR核心分析包,用于添加日志文件、启动/停止LogMiner分析
DBMS_LOGMNR_D辅助包,用于创建和管理数据字典文件

这两个包分别由以下脚本创建:

-- 以SYS用户执行@$ORACLE_HOME/rdbms/admin/dbmslm.sql-- 创建DBMS_LOGMNR包@$ORACLE_HOME/rdbms/admin/dbmslmd.sql-- 创建DBMS_LOGMNR_D包

核心动态视图

视图说明
V$LOGMNR_DICTIONARY显示用于决定对象ID名称的字典文件信息
V$LOGMNR_PARAMETERS查询当前LogMiner设定的参数
V$LOGMNR_LOGS在LogMiner启动时显示待分析的日志列表
V$LOGMNR_CONTENTS最重要的视图,包含解析后的日志内容

注意事项

  1. 在 19c 多租户(CDB)架构下,LogMiner 必须在CDB 根容器下执行,在 PDB 中执行会报错。
  2. 所有操作必须在同一个数据库会话(Session)中连续执行。如果断开重连,V$LOGMNR_CONTENTS视图中的结果将丢失。

1.4 数据字典选项

当LogMiner分析重做数据时,需要一个数据字典将日志中的对象ID转换为可读的表名和列名。如果没有数据字典,LogMiner解释出来的语句中关于数据字典的部分(如表名、列名等)都将是16进制的形式,无法直接理解。

LogMiner提供了三种使用数据字典的方式:

方式说明命令
在线目录(Online Catalog)使用当前数据库的在线数据字典,必须在源数据库执行DBMS_LOGMNR.START_LOGMNR(options=>DBMS_LOGMNR.DICT_FROM_ONLINE_CATALOG)
提取到重做日志将字典提取到重做日志流中,要求数据库处于ARCHIVELOG模式且为OPEN状态DBMS_LOGMNR_D.BUILD(options=>DBMS_LOGMNR_D.STORE_IN_REDO_LOGS)
提取到操作系统文件将字典导出为文本文件,需设置UTL_FILE_DIR参数DBMS_LOGMNR_D.BUILD('filename','directory',DBMS_LOGMNR_D.STORE_IN_FLAT_FILE)

方式对比

  • 在线目录:最简单,无需额外步骤,但只能分析当前数据库的日志
  • 提取到重做日志:适合长期归档分析,字典与日志一起归档
  • 提取到文件:适合跨数据库分析,但需要配置UTL_FILE_DIR并重启数据库

1.5关键前置条件:补充日志 (Supplemental Logging)

在使用 LogMiner 进行数据恢复前,强烈建议开启最小补充日志

  • 未开启时:Oracle 仅记录恢复数据块所需的最小信息。对于UPDATE操作,LogMiner 可能无法获取修改前的旧值(SQL_UNDO中的旧值可能为NULL),且WHERE条件可能依赖物理地址ROWID,导致生成的回滚 SQL 无法在其他环境执行。
  • 开启后:Oracle 会在重做日志中记录足够的列信息(如主键或修改前的值),确保生成的SQL_REDOSQL_UNDO逻辑完整、准确可用。
-- 启用最小补充日志 ALTER DATABASE ADD SUPPLEMENTAL LOG DATA; -- 更全面的补充日志(推荐) ALTER DATABASE ADD SUPPLEMENTAL LOG DATA (PRIMARY KEY) COLUMNS; -- 验证是否启用 SELECT supplemental_log_data_min, supplemental_log_data_pk, supplemental_log_data_ui, supplemental_log_data_fk, supplemental_log_data_all FROM v$database; SUPPLEMENTAL_LOG_DATA_MIN应返回 'YES' 或 'IMPLICIT'

二、简单使用案例

1、补充日志开启确认 SELECT supplemental_log_data_min, supplemental_log_data_pk, supplemental_log_data_ui, supplemental_log_data_fk, supplemental_log_data_all FROM v$database; SUPPLEME SUP SUP SUP SUP -------- --- --- --- --- YES YES NO NO NO 2、做一些测试操作 [oracle@host51 ~]$ sqlplus user1/user1 SQL> select count(*) from emp; SQL> select count(*) from dept; COUNT(*) ---------- 4 SQL> insert into emp select * from scott.emp; 14 rows created. SQL> commit; Commit complete. SQL> alter system archive log current; System altered. SQL> delete from dept; 4 rows deleted. SQL> commit; Commit complete. SQL> alter system archive log current; System altered. SQL> create table tab1 as select * from dba_users; Table created. SQL> select to_char(sysdate,'yyyymmdd hh24:mi:ss') from dual; TO_CHAR(SYSDATE,' ----------------- 20260806 15:28:06 3、指定 LogMiner 数据字典(这里我们选择直接从在线目录获取) EXEC DBMS_LOGMNR_D.BUILD(OPTIONS => DBMS_LOGMNR_D.STORE_IN_REDO_LOGS); 4、添加需要挖掘的日志文件 -- 1)生成添加归档日志的执行脚本(根据实际时间范围修改) SELECT DISTINCT 'EXEC DBMS_LOGMNR.ADD_LOGFILE(LOGFILENAME=>''' || name || ''', OPTIONS=>DBMS_LOGMNR.ADDFILE);' AS add_log_sql FROM GV$ARCHIVED_LOG WHERE completion_time BETWEEN TO_DATE('2026-08-06 15:26:00', 'YYYY-MM-DD HH24:MI:SS') AND TO_DATE('2026-08-06 15:29:00', 'YYYY-MM-DD HH24:MI:SS') AND dest_id = 1 ORDER BY 1; -- 2)在 SQL*Plus 中执行上述生成的脚本,批量添加日志 -- (如果是第一个文件,请将 OPTIONS 改为 DBMS_LOGMNR.NEW) 具体如下: EXEC DBMS_LOGMNR.ADD_LOGFILE(LOGFILENAME=>'/oradata/orcl/fast_recovery_area/ORCL/archivelog/2026_08_06/o1_mf_1_6_o78ftzoz_.arc', OPTIONS=>DBMS_LOGMNR.new); EXEC DBMS_LOGMNR.ADD_LOGFILE(LOGFILENAME=>'/oradata/orcl/fast_recovery_area/ORCL/archivelog/2026_08_06/o1_mf_1_7_o78fvd9b_.arc', OPTIONS=>DBMS_LOGMNR.ADDFILE); 5、启动 LogMiner 会话 EXEC DBMS_LOGMNR.START_LOGMNR(OPTIONS => DBMS_LOGMNR.DICT_FROM_ONLINE_CATALOG); 6、查询挖掘结果 --由于视图数据量可能极大,且会话已断开,就会丢失视图里面的内容,建议先将结果存入临时表,再进行查询分析 CREATE TABLE t_logminer_res AS SELECT scn,timestamp, operation, table_name, sql_redo, sql_undo FROM v$logmnr_contents WHERE seg_owner = 'USER1' ORDER BY 1; 查询临时表,类似如下 SQL> select * from t_logminer_res; SCN TIMESTAMP OPERATION ---------- ------------ -------------------------------- TABLE_NAME -------------------------------- SQL_REDO -------------------------------------------------------------------------------- SQL_UNDO -------------------------------------------------------------------------------- 1126344 06-AUG-26 INSERT EMP insert into "USER1"."EMP"("EMPNO","ENAME","JOB","MGR","HIREDATE","SAL","COMM","D EPTNO") values ('7369','SMITH','CLERK','7902',TO_DATE('17-DEC-80', 'DD-MON-RR'), '800',NULL,'20'); delete from "USER1"."EMP" where "EMPNO" = '7369' and "ENAME" = 'SMITH' and "JOB" = 'CLERK' and "MGR" = '7902' and "HIREDATE" = TO_DATE('17-DEC-80', 'DD-MON-RR') and "SAL" = '800' and "COMM" IS NULL and "DEPTNO" = '20' and ROWID = 'AAAVVUAAF AAAACDAAA'; ...... 根据找到对应的 SQL_UNDO 或原始的 CREATE/REPLACE PROCEDURE 语句后,交由开发人员确认无误,即可恢复存储过程 7、结束 LogMiner 会话 分析完成后,务必结束会话以释放 PGA/SGA 内存资源: EXEC DBMS_LOGMNR.END_LOGMNR; 至此简单测试案例完成!

三、使用案例(详细讲解)

3.1 环境准备与配置

步骤1:确认补充日志已启用

补充日志(Supplemental Logging)必须在生成待分析的重做日志之前启用,否则LogMiner挖掘的一些信息无法正常显示。

-- 查看补充日志状态SELECTsupplemental_log_data_min,supplemental_log_data_pk,supplemental_log_data_ui,supplemental_log_data_fk,supplemental_log_data_allFROMv$database;-- 如果返回结果为NO,执行以下命令启用ALTERDATABASEADDSUPPLEMENTAL LOGDATA;-- 更全面的补充日志(推荐)ALTERDATABASEADDSUPPLEMENTAL LOGDATA(PRIMARYKEY)COLUMNS;

步骤2:确认/安装LogMiner包

-- 检查DBMS_LOGMNR包是否存在SELECTowner,object_name,object_typeFROMdba_objectsWHEREobject_nameLIKE'DBMS_LOGMNR%';-- 如果不存在,以SYS用户执行安装脚本@$ORACLE_HOME/rdbms/admin/dbmslm.sql@$ORACLE_HOME/rdbms/admin/dbmslmd.sql

步骤3:设置数据字典目录(如使用文件方式)

-- 创建目录CREATEDIRECTORY logminer_dirAS'/u01/app/oracle/logminer';-- 设置UTL_FILE_DIR参数(需要重启数据库)ALTERSYSTEMSETUTL_FILE_DIR='/u01/app/oracle/logminer'SCOPE=SPFILE;-- 然后重启数据库

2.2 生成数据字典(文件方式)

如果选择将数据字典提取到操作系统文件(注意需要重启数据库):

-- 创建数据字典文件BEGINDBMS_LOGMNR_D.BUILD(dictionary_filename=>'dictionary.ora',dictionary_location=>'/u01/app/oracle/logminer');END;/[oracle@host51logminer]$ ls-ltr/u01/app/oracle/logminer-rw-r--r-- 1 oracle oinstall 41111786 Aug 6 15:47 dictionary.ora --可以看到数据字典(文件形式)备注:如果不重启数据库,报错如下 ERROR at line1: ORA-01308: initialization parameter utl_file_dirisnotsetORA-06512: at"SYS.DBMS_LOGMNR_INTERNAL",line6110ORA-06512: at"SYS.DBMS_LOGMNR_INTERNAL",line6200ORA-06512: at"SYS.DBMS_LOGMNR_D",line12ORA-06512: at line2

2.3 添加待分析的日志文件

使用DBMS_LOGMNR.ADD_LOGFILE过程添加需要分析的日志文件:

-- 第一次添加使用NEW选项(清空之前的日志列表)BEGINDBMS_LOGMNR.ADD_LOGFILE(LOGFILENAME=>'/u01/app/oracle/oradata/mydb/redo01.log',OPTIONS=>DBMS_LOGMNR.NEW);END;/-- 继续添加其他日志文件使用ADDFILE选项BEGINDBMS_LOGMNR.ADD_LOGFILE(LOGFILENAME=>'/u01/app/oracle/oradata/mydb/redo02.log',OPTIONS=>DBMS_LOGMNR.ADDFILE);END;/-- 添加归档日志文件BEGINDBMS_LOGMNR.ADD_LOGFILE(LOGFILENAME=>'/u01/app/oracle/archivelog/arch_1_12345.arc',OPTIONS=>DBMS_LOGMNR.ADDFILE);END;/

2.4 启动LogMiner

使用DBMS_LOGMNR.START_LOGMNR启动LogMiner分析会话:

方式一:使用在线目录(最常用)

BEGINDBMS_LOGMNR.START_LOGMNR(OPTIONS=>DBMS_LOGMNR.DICT_FROM_ONLINE_CATALOG);END;/

方式二:使用字典文件

BEGINDBMS_LOGMNR.START_LOGMNR(DICTFILENAME=>'/u01/app/oracle/logminer/dictionary.ora',OPTIONS=>DBMS_LOGMNR.DDL_DICT_TRACKING);END;/

2.5 查询分析结果

启动LogMiner后,通过查询V$LOGMNR_CONTENTS视图获取解析后的日志内容:

-- 查看所有解析结果SELECTscn,timestamp,username,seg_owner,table_name,operation,sql_redo,sql_undoFROMv$logmnr_contentsORDERBYscn;-- 查看特定用户的操作SELECTscn,timestamp,operation,sql_redo,sql_undoFROMv$logmnr_contentsWHEREseg_owner='USER1'ORDERBYscn;-- 查看特定表的DML操作SELECTscn,timestamp,operation,sql_redo,sql_undoFROMv$logmnr_contentsWHEREseg_owner='USER1'ANDtable_name='EMP'ANDoperationIN('INSERT','UPDATE','DELETE')ORDERBYscn;-- 查看特定时间段的操作SELECTscn,timestamp,username,sql_redoFROMv$logmnr_contentsWHEREtimestampBETWEENTO_DATE('2026-08-01 10:00:00','YYYY-MM-DD HH24:MI:SS')ANDTO_DATE('2026-08-01 12:00:00','YYYY-MM-DD HH24:MI:SS');-- 查看DDL操作SELECTscn,timestamp,username,operation,sql_redoFROMv$logmnr_contentsWHEREoperationLIKE'DDL%';-- 查看已提交的事务(仅显示已提交的变更)SELECTscn,timestamp,operation,sql_redo,sql_undoFROMv$logmnr_contentsWHEREcommit_scnISNOTNULL;

2.6 结束LogMiner会话

分析完成后,关闭LogMiner以释放资源:

EXECDBMS_LOGMNR.END_LOGMNR;

2.7 完整案例演示

以下是一个完整的LogMiner使用案例:

步骤1:创建测试表并执行操作

-- 创建测试表CREATETABLEtest_logminer(id NUMBER,name VARCHAR2(50),create_timeDATE);-- 插入数据INSERTINTOtest_logminerVALUES(1,'Tom',SYSDATE);INSERTINTOtest_logminerVALUES(2,'Mary',SYSDATE);INSERTINTOtest_logminerVALUES(3,'Mike',SYSDATE);COMMIT;-- 更新数据UPDATEtest_logminerSETname='Tom_Updated'WHEREid=1;COMMIT;-- 删除数据DELETEFROMtest_logminerWHEREid=3;COMMIT;-- 执行DDLALTERTABLEtest_logminerADD(statusVARCHAR2(10));

步骤2:强制日志切换

-- 确保日志已写入归档ALTERSYSTEM SWITCH LOGFILE;ALTERSYSTEM SWITCH LOGFILE;

步骤3:启动LogMiner分析

-- 添加当前在线日志(或归档日志)-- 1)生成添加归档日志的执行脚本(根据实际时间范围修改)SELECTDISTINCT'EXEC DBMS_LOGMNR.ADD_LOGFILE(LOGFILENAME=>'''||name||''', OPTIONS=>DBMS_LOGMNR.ADDFILE);'ASadd_log_sqlFROMGV$ARCHIVED_LOGWHEREcompletion_timeBETWEENTO_DATE('2026-08-06 15:26:00','YYYY-MM-DD HH24:MI:SS')ANDTO_DATE('2026-08-06 15:29:00','YYYY-MM-DD HH24:MI:SS')ANDdest_id=1ORDERBY1;-- 2)在 SQL*Plus 中执行上述生成的脚本,批量添加日志-- (如果是第一个文件,请将 OPTIONS 改为 DBMS_LOGMNR.NEW)EXECDBMS_LOGMNR.ADD_LOGFILE(LOGFILENAME=>'/oradata/orcl/fast_recovery_area/ORCL/archivelog/2026_08_06/o1_mf_1_8_o78fyb2g_.arc',OPTIONS=>DBMS_LOGMNR.new);EXECDBMS_LOGMNR.ADD_LOGFILE(LOGFILENAME=>'/oradata/orcl/fast_recovery_area/ORCL/archivelog/2026_08_06/o1_mf_1_9_o78fybk4_.arc',OPTIONS=>DBMS_LOGMNR.ADDFILE);-- 启动LogMiner(使用在线数据字典)BEGINDBMS_LOGMNR.START_LOGMNR(OPTIONS=>DBMS_LOGMNR.DICT_FROM_ONLINE_CATALOG);END;/

步骤4:查询分析结果

-- 查看测试表的所有变更SELECTscn,TO_CHAR(timestamp,'YYYY-MM-DD HH24:MI:SS')ASop_time,operation,sql_redo,sql_undoFROMv$logmnr_contentsWHEREseg_owner=USERANDtable_name='TEST_LOGMINER'ORDERBYscn;

输出示例:

SCN OP_TIME OPERATION ---------- ------------------- -------------------------------- SQL_REDO -------------------------------------------------------------------------------- SQL_UNDO -------------------------------------------------------------------------------- 1155998 2026-08-06 15:57:39 DDL CREATE TABLE test_logminer ( id NUMBER, name VARCHAR2(50), create_time DATE ); 1156010 2026-08-06 15:57:44 INSERT insert into "USER1"."TEST_LOGMINER"("COL 1","COL 2","COL 3") values (HEXTORAW('c 102'),HEXTORAW('546f6d'),HEXTORAW('787e0806103a2d')); delete from "USER1"."TEST_LOGMINER" where "COL 1" = HEXTORAW('c102') and "COL 2" = HEXTORAW('546f6d') and "COL 3" = HEXTORAW('787e0806103a2d') and ROWID = 'AAAV XvAAFAAAACnAAA'; ......

步骤5:结束会话

EXECDBMS_LOGMNR.END_LOGMNR;

2.8 典型应用场景

场景一:误操作数据恢复

当用户误删除或误更新数据时,可通过LogMiner找到对应的SQL_UNDO语句执行回退:

-- 找到误操作对应的UNDO SQLSELECTsql_undo,timestamp,usernameFROMv$logmnr_contentsWHEREseg_owner='SCOTT'ANDtable_name='EMP'ANDoperation='DELETE'ANDtimestamp>SYSDATE-1/24;-- 最近1小时

场景二:数据库变更审计

追踪特定用户或特定时间段的所有数据变更:

SELECTusername,operation,table_name,TO_CHAR(timestamp,'YYYY-MM-DD HH24:MI:SS')ASop_time,sql_redoFROMv$logmnr_contentsWHEREusername='APP_USER'ANDtimestampBETWEENTO_DATE('2025-08-01 00:00:00','YYYY-MM-DD HH24:MI:SS')ANDTO_DATE('2025-08-01 23:59:59','YYYY-MM-DD HH24:MI:SS')ORDERBYtimestamp;

场景三:分析数据增长模式

通过分析INSERT操作,了解数据增长趋势:

SELECTTO_CHAR(timestamp,'YYYY-MM-DD')ASday,COUNT(*)ASinsert_count,seg_owner,table_nameFROMv$logmnr_contentsWHEREoperation='INSERT'ANDtimestamp>SYSDATE-30GROUPBYTO_CHAR(timestamp,'YYYY-MM-DD'),seg_owner,table_nameORDERBYdayDESC;

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询