dba有时候需要被数据丢失的锅,去找回或者找到数据是否“丢失”的原因,这个时候如果归档还在,我们就可以用oracle自带的logmnr来分析归档日志了。
一.安装LogMiner
$ sqlplus /nolog
SQL*Plus: Release 10.2.0.3.0 - Production on Tue Apr 15 12:30:58 2008
Copyright (c) 1982, 2006, Oracle. All Rights Reserved.
SQL> conn / as sysdba;
Connected to an idle instance.
SQL> startup
ORACLE instance started.
Total System Global Area 1392508928 bytes
Fixed Size 2072808 bytes
Variable Size 738201368 bytes
Database Buffers 637534208 bytes
Redo Buffers 14700544 bytes
Database mounted.
Database opened.
SQL>@?/rdbms/admin/dbmslm.sql
Package created.
Grant succeeded.
--dbmslm.sql是用来创建DBMS_LOGMNR的package,这个包是用来分析日志的.
SQL>@?/rdbms/admin/dbmslmd.sql
Package created.
--dbmslmd.sql是用来创建DBMS_LOGMNR_D的package的,这个包是用来创建数据字典文件的.
注意以上两个包都是需要在sysdba权限的user下创建.
二.使用LogMiner
安装LogMiner确实很简单,现在来看看如何使用我们安装好的东东
1.首先需要创建数据字典文件(data-dictionary):
为什么要创建数据字典文件呢?
引用一位网友的话就是:让LogMiner引用涉及到内部数据字典中的部分时为他们实际的名字,而不是系统内部的16进制。数据字典文件是一个文本文件,使用包 DBMS_LOGMNR_D来创建。如果我们要分析的数据库中的表有变化,影响到库的数据字典也发生变化,这时就需要重新创建该字典文件。另外一种情况是在分析另外一个数据库文件的重作日志时,也必须要重新生成一遍被分析数据库的数据字典文件。 在使用LogMiner工具分析redo log文件之前,可以使用DBMS_LOGMNR_D 包将数据字典导出为一个文本文件。该字典文件是可选的,但是如果没有它,LogMiner解释出来的语句中关于数据字典中的部分(如表名、列名等)和数值都将是16进制的形式,我们是无法直接理解的。
在pfile或者spfile中,我们通过设定UTL_FILE_DIR参数来指定数据字典文件的位置目录
对于UTL_FILE_DIR参数在10g的文档中有这样的解释:
----------------------------------------------
UTL_FILE_DIR lets you specify one or more directories that Oracle should use for PL/SQL file I/O. If you are specifying multiple directories, you must repeat the UTL_FILE_DIR parameter for each directory on separate lines of the initialization parameter file.
All users can read or write to all files specified by this parameter. Therefore all PL/SQL users must be trusted with the information in the directories specified by this parameter.
Note:
If you list multiple values, all entries of this parameter must be on contiguous lines of the parameter file. If you separate them with other parameters, Oracle will read only the last (contiguous) lines.
开始设置UTL_FILE_DIR参数并创建数据字典文件:
SQL> show parameter spfile;
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
spfile string /opt/oracle/product/10g/dbs/sp
fileirmdb.ora
SQL> alter system set UTL_FILE_DIR='/opt/oracle/product/10g/logmnr' scope=spfile;
System altered.
SQL> shutdown immediate;
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL> startup
ORACLE instance started.
Total System Global Area 1392508928 bytes
Fixed Size 2072808 bytes
Variable Size 738201368 bytes
Database Buffers 637534208 bytes
Redo Buffers 14700544 bytes
Database mounted.
Database opened.
SQL> show parameter UTL_FILE_DIR
NAME TYPE VALUE
------------------------------------ ----------- ----------------------------
utl_file_dir string /opt/oracle/product/10g/logmnr
现在开始创建数据字典:
SQL> show user;
USER is "SYS"
SQL>exec dbms_logmnr_d.build(dictionary_filename=>'alan_dict.ora',dictionary_location=>'/opt/oracle/product/10g/logmnr');
PL/SQL procedure successfully completed.
SQL> !
$ cd $ORACLE_HOME/logmnr
$ ls
alan_dict.ora
2.其次需要创建分析的日志文件列表:
首先看一下dbms_logmnr包的内容:
SQL> desc dbms_logmnr;
PROCEDURE ADD_LOGFILE
Argument Name Type In/Out Default?
------------------------------ ----------------------- ------ --------
LOGFILENAME VARCHAR2 IN
OPTIONS BINARY_INTEGER IN DEFAULT
FUNCTION COLUMN_PRESENT RETURNS BINARY_INTEGER
Argument Name Type In/Out Default?
------------------------------ ----------------------- ------ --------
SQL_REDO_UNDO NUMBER IN DEFAULT
COLUMN_NAME VARCHAR2 IN DEFAULT
PROCEDURE END_LOGMNR
FUNCTION MINE_VALUE RETURNS VARCHAR2
Argument Name Type In/Out Default?
------------------------------ ----------------------- ------ --------
SQL_REDO_UNDO NUMBER IN DEFAULT
COLUMN_NAME VARCHAR2 IN DEFAULT
PROCEDURE REMOVE_LOGFILE
Argument Name Type In/Out Default?
------------------------------ ----------------------- ------ --------
LOGFILENAME VARCHAR2 IN
PROCEDURE START_LOGMNR
Argument Name Type In/Out Default?
------------------------------ ----------------------- ------ --------
STARTSCN NUMBER IN DEFAULT
ENDSCN NUMBER IN DEFAULT
STARTTIME DATE IN DEFAULT
ENDTIME DATE IN DEFAULT
DICTFILENAME VARCHAR2 IN DEFAULT
OPTIONS BINARY_INTEGER IN DEFAULT
SQL> select group#,status from v$log;
GROUP# STATUS
---------- ----------------
1 CURRENT
2 INACTIVE
3 INACTIVE
SQL> select member from v$logfile;
MEMBER
--------------------------------------------------------------------------------
/opt/oracle/oradata/irmdb/redo03.log
/opt/oracle/oradata/irmdb/redo02.log
/opt/oracle/oradata/irmdb/redo01.log
创建分析列表:
SQL>exec dbms_logmnr.add_logfile(LogFileName=>'/opt/oracle/oradata/irmdb/redo01.log',Options=>dbms_logmnr.new);
PL/SQL procedure successfully completed.
SQL>exec dbms_logmnr.add_logfile(LogFileName=>'/opt/oracle/oradata/irmdb/redo02.log',Options=>dbms_logmnr.ADDFILE);
PL/SQL procedure successfully completed.
SQL>exec dbms_logmnr.add_logfile(LogFileName=>'/opt/oracle/oradata/irmdb/redo03.log',Options=>dbms_logmnr.ADDFILE);
PL/SQL procedure successfully completed.
这样不仅仅创建了日志分析列表,同时还添加了两个日志成员文件。
通过观察v$logmnr_logs动态性能视图我们可以看到分析列表中目前的日志成员:
SQL>select filename from v$logmnr_logs;
FILENAME
--------------------------------------------------------------------------------
/opt/oracle/oradata/irmdb/redo02.log
/opt/oracle/oradata/irmdb/redo03.log
/opt/oracle/oradata/irmdb/redo01.log
SQL> exec dbms_logmnr.remove_logfile('/opt/oracle/oradata/irmdb/redo02.log');
PL/SQL procedure successfully completed.
SQL> select filename from v$logmnr_logs;
FILENAME
--------------------------------------------------------------------------------
/opt/oracle/oradata/irmdb/redo03.log
/opt/oracle/oradata/irmdb/redo01.log
SQL> exec dbms_logmnr.add_logfile(LogFileName=>'/opt/oracle/oradata/irmdb/redo02.log',Options=>dbms_logmnr.ADDFILE);
PL/SQL procedure successfully completed.
3.利用LogMnr进行日志挖掘和分析:
挖掘和分析分为两种情况,一种是利用数据字典文件对所有分析列表中的日志内容进行分析,另外一种是利用数据字典文件并带有某种的限制条件对日志内容进行分析,比如从某个时间点到某个时间点日志内容的分析:
这里列出一下dbms_logmnr.start_logmnr的结构:
PROCEDURE START_LOGMNR
Argument Name Type In/Out Default?
------------------------------ ----------------------- ------ --------
STARTSCN NUMBER IN DEFAULT
ENDSCN NUMBER IN DEFAULT
STARTTIME DATE IN DEFAULT
ENDTIME DATE IN DEFAULT
DICTFILENAME VARCHAR2 IN DEFAULT
OPTIONS BINARY_INTEGER IN DEFAULT
对第一种情况进行分析:
-----------------------------------------
SQL>exec dbms_logmnr.start_logmnr(DictFileName=>'/opt/oracle/product/10g/logmnr/alan_dict.ora');
PL/SQL procedure successfully completed.
分析完毕后所有分析的内容都保存到了GV$LOGMNR_CONTENTS动态性能视图里面,我们可以通过如下SQL来查询我们感兴趣的内容。
select scn,timestamp,log_id,seg_owner,seg_type,
table_space,data_blk#,data_obj#,data_objd#,
session#,serial#,username,session_info,
sql_redo,sql_undo from GV$LOGMNR_CONTENTS t
where t.sql_redo like 'create%';
最后我们可以释放内存:
SQL> exec dbms_logmnr.end_logmnr;
PL/SQL procedure successfully completed.
对第二种情况进行分析:
----------------------------------------
同时我们可以利用scn或time做为分析的限制条件,比如我们要分析日志列表中时间从08.04.13从10:00到15:00的内容。
SQL>exec dbms_logmnr.start_logmnr
(startTime => to_date('20080413100000','yyyy-mm-dd hh24:mi:ss'),
endTime => to_date('20080413150000','yyyy-mm-dd hh24:mi:ss'),
DictFileName=>'/opt/oracle/product/10g/logmnr/alan_dict.ora');
PL/SQL procedure successfully completed
之后的操作就是查询v$logmnr_contents或者gv$logmnr_contents视图并进一步的分析
同时不要忘记最后释放内存:
SQL>exec dbms_logmnr.end_logmnr;