题目部分
在Oracle中,LogMiner是什么?其有哪些用途?请简述LogMiner的使用过程。
答案部分
众所周知,所有对用户数据和数据字典的改变都记录在Oracle的Redo日志中,因此,Redo日志包含了所有进行恢复操作所需要的信息。但是,原始的Redo日志文件无法看懂,所以,Oracle从8i以后提供了一个非常有用的分析工具,称为LogMiner。使用该工具可以轻松获得Redo日志文件(包含归档日志文件)中的具体内容。特别是该工具可以分析出所有对于数据库的DML操作(INSERT、UPDATE、DELETE等)语句。Oracle 9i后可以分析DDL语句,另外还可分析得到一些必要的回滚SQL语句。LogMiner一个最重要的用途就是不用全部恢复数据库就可以恢复数据库的某个变化。该工具特别适用于调试、审计或者回退某个特定的事务。
LogMiner工具既可以用来分析在线日志,也可以用来分析离线日志文件,既可以分析本身自己数据库的重作日志文件,也可以用来分析其它数据库的重作日志文件。当分析其它数据库的重作日志文件时,需要注意的是,LogMiner必须使用被分析数据库实例产生的字典文件,而不是安装LogMiner的数据库产生的字典文件,另外,必须保证安装LogMiner数据库的字符集和被分析数据库的字符集相同。源数据库(Source Database)平台必须和分析数据库(Mining Database)平台一样。
Oracle通过LogMiner工具对Redo日志进行挖掘,显示出一系列可读的信息,该过程称为日志挖掘。LogMiner通过V$LOGMNR_CONTENTS视图显示Redo日志中的信息。
总的说来,LogMiner工具的主要用途有:
1、跟踪数据库的变化:可以离线地跟踪数据库的变化,而不会影响在线系统的性能
2、回退数据库的变化:回退特定的变化数据,减少Point-In-Time Recovery的执行
3、优化和扩容计划:可通过分析日志文件中的数据以分析数据的增长模式
4、确定数据库的逻辑损坏时间:准确定位操作执行的时间和SCN
5、确定事务级要执行的精细逻辑恢复操作,可以取得相应的Undo操作
6、执行后续审计
(一)安装LogMiner工具
在默认情况下,Oracle已经安装了LogMiner工具。若是没有安装,则可以运行下面两个脚本:
代码语言:javascript复制$ORACLE_HOME/rdbms/admin/dbmslm.sql
$ORACLE_HOME/rdbms/admin/dbmslmd.sql
这两个脚本必须均以SYS用户身份运行。其中第一个脚本用来创建DBMS_LOGMNR包,该包用来分析日志文件。第二个脚本用来创建DBMS_LOGMNR_D包,该包用来创建数据字典文件。若要使普通用户具有日志挖掘的权限,则可以执行如下的SQL进行赋权:
代码语言:javascript复制GRANT EXECUTE ON DBMS_LOGMNR TO LHR_TEST;
脚本执行完毕后,LogMiner包含两个PL/SQL包和几个视图:
1、DBMS_LOGMNR_D包,包括一个用于提取数据字典信息的过程,即DBMS_LOGMNR_D.BUILD()过程,还包含一个重建LogMiner表的过程,DBMS_LOGMNR_D.SET_TABLESPACE。在默认情况下,LogMiner的表是建在SYSTEM表空间下的。
2、DBMS_LOGMNR包,它有3个存储过程:
l ADD_LOGFILE(NAME VARCHAR2,OPTIONS NUMBER) 用来添加或删除用于分析的日志文件
l START_LOGMNR(START_SCN NUMBER,END_SCN NUMBER,START_TIME NUMBER,END_TIME NUMBER,DICTFILENAME VARCHAR2,OPTIONS NUMBER) 用来开启日志分析,同时确定分析的时间或SCN窗口以及确认是否使用提取出来的数据字典信息
l END_LOGMNR()存储过程用来终止分析会话,它将回收LogMiner所占用的内存
与LogMiner相关的数据字典视图:
l V$LOGHIST:显示历史日志文件的一些信息
l V$LOGMNR_DICTIONARY:因为LOGMINER可以有多个字典文件,所以该视图显示字典文件信息
l V$LOGMNR_PARAMETERS:显示LOGMINER的参数
l V$LOGMNR_LOGS:显示用于分析的日志列表信息
l V$LOGMNR_CONTENTS:LOGMINER结果
(二)LogMiner的数据字典
为了完全地转换Redo日志中的内容,LogMiner需要访问一个数据库字典。LogMiner使用该字典将Oracle内部的对象标识符和数据类型转换为对象名称和外部的数据格式。没有字典,LogMiner将使用16进制字符显示内部对象ID。
例如,对于如下的SQL语句:
代码语言:javascript复制INSERT INTO emp(name, salary) VALUES ('John Doe', 50000);
在没有数据字典的情况下,LogMiner将显示为:
代码语言:javascript复制INSERT INTO Object#2581(col#1, col#2) VALUES (hextoraw('4a6f686e20446f65'),hextoraw('c306'));"
LogMiner提供了3种提取字典文件的方式:
① 将字典文件提取为一个Flat File(平面文件或中间接口文件)
② 将字典文件提取为Redo日志
③ 使用Online Catalog(联机日志)
下面分别介绍这3种方式:
① 将字典文件提取为一个Flat File(平面文件或中间接口文件)
为了将数据库字典信息提取为Flat File,需要使用带有STORE_IN_FLAT_FILE参数的DBMS_LOGMNR_D.BUILD程序。DBMS_LOGMNR_D.BUILD程序需要访问一个能够放置字典文件的目录。因为PL/SQL 程序通常不能直接访问用户目录,必须手动指定一个由DBMS_LOGMNR_D.BUILD程序使用的目录。为了指定该目录,必须修改初始化文件中的UTL_FILE_DIR参数:
代码语言:javascript复制ALTER SYSTEM SET UTL_FILE_DIR ='/home/oracle' SCOPE=SPFILE;
然后重新启动数据库。确保在创建Flat File文件的过程中,不能有DDL操作被执行。在创建Flat File文件时,数据库必须处于OPEN状态,然后执行DMBS_LOGMNR_D.BUILD程序:
代码语言:javascript复制EXECUTE DBMS_LOGMNR_D.BUILD('dictionary.ora', '/home/oracle');
脚本执行完成后会在/home/oracle下生成一个dictionary.ora的文本文件。该文件中包含一系列的建表语句和插入语句。
② 将字典文件提取为Redo日志
为了将字典文件提取为Redo日志,数据库必须处于OPEN状态,并且处于归档模式。将字典提取为Redo日志的过程中,数据库系统不能有DDL语句被执行。为了将字典提取为Redo日志,需要使用带有STORE_IN_REDO_FILES参数的DBMS_LOGMNR_D.BUILD程序:
代码语言:javascript复制SQL> EXECUTE DBMS_LOGMNR_D.BUILD(OPTIONS=>DBMS_LOGMNR_D.STORE_IN_REDO_LOGS);
需要注意的是,将字典文件提取为Redo文件的时候需要开启附加日志,如下所示:
代码语言:javascript复制ALTER DATABASE ADD SUPPLEMENTAL LOG DATA;
在这些Redo日志被归档之后,可以通过查询V$ARCHIVED_LOG视图来查询:
代码语言:javascript复制SELECT *
FROM V$ARCHIVED_LOG A
WHERE A.NAME IS NOT NULL
AND (A.DICTIONARY_BEGIN = 'YES' OR A.DICTIONARY_END = 'YES');
如果将字典信息提取为Redo文件,那么在使用DBMD_LOGMNR.ADD_LOGFILE指定所需要分析的日志文件时,需要将这些包含字典信息的Redo文件也添加进去。同时在使用START_LOGMNR开始分析时,需要指定DICT_FROM_REDO_LOGS的参数。
③ 使用Online Catalog(联机日志)
为了使LogMiner直接使用数据库当前使用的字典,在开始LogMiner时可以指定将联机目录作为字典源:
代码语言:javascript复制SQL> EXECUTE DBMS_LOGMNR.START_LOGMNR(OPTIONS => DBMS_LOGMNR.DICT_FROM_ONLINE_CATALOG);
使用联机目录,意味着不需要再提取字典文件,是开始分析日志的最快的方式。除了可以分析联机Redo日志外,还可以在和产生归档日志文件相同的系统上分析归档日志文件。然而,记住联机目录只能重建应用于表的最新版本上的SQL语句。一旦表被修改,联机目录就无法反映出表之前的版本。这就意味着LogMiner不能重建执行于表的旧版本上的SQL语句。
(三)跟踪DDL语句
当LogMiner被启动时,它会自动创建自己的内部字典。如果源字典是Flat File字典或Redo日志中的字典,则可以使用DDL_DICT_TRACKING参数来跟踪DDL语句。DDL跟踪默认是关闭的。为了打开这一功能,可以在启动LogMiner时使用DDL_DICT_TRACKING参数:
代码语言:javascript复制SQL> EXECUTE DBMS_LOGMNR.START_LOGMNR(OPTIONS =>DBMS_LOGMNR.DDL_DICT_TRACKING);
当使用DDL_DICT_TRACKING时,需要注意如下几点:
v 当使用联机目录(Online catalog)时,也就是当使用DICT_FROM_ONLINE_CATALOG参数时,是不能使用DDL_DICT_TRACKING选项的。
v 使用DDL_DICT_TRACKING时,要求数据库处于OPEN状态。
v 尽量为LogMiner的表提供一个单独的表空间。默认情况下LogMiner的表是创建在SYSTEM表空间中的。使用DBMS_LOGMNR_D.SET_TABLESPACE可以在一个单独的表空间中重建这些LogMiner的表:SQL> EXECUTE DBMS_LOGMNR_D.SET_TABLESPACE('logmnrts$');。
(四)过滤LogMiner返回的数据
可以使用COMMITTED_DATA_ONLY参数来只显示那些被提交的事务:
代码语言:javascript复制SQL> EXEC DBMS_LOGMNR.START_LOGMNR(OPTIONS=>DBMS_LOGMNR.COMMITTED_DATA_ONLY);
当使用这一参数时,LogMiner将所有的DML操作按照事务的关系组合在一起。这些事务按照它们被提交的顺序显示出来。
可以使用SKIP_CORRUPTION参数来忽略Redo日志中的所有错误:
代码语言:javascript复制SQL> EXECUTE DBMS_LOGMNR.START_LOGMNR(OPTIONS =>DBMS_LOGMNR.SKIP_CORRUPTION);
可以使用使用STARTTIME和ENDTIME参数按照时间过滤数据,还可以使用STARTSCN和ENDSCN参数按照SCN(System Change Number)来过滤数据。
代码语言:javascript复制BEGIN
DBMS_LOGMNR.START_LOGMNR(STARTSCN => 23573690,ENDSCN => 23632671,OPTIONS => DBMS_LOGMNR.DICT_FROM_ONLINE_CATALOG DBMS_LOGMNR.CONTINUOUS_MINE);
END;
/
BEGIN
DBMS_LOGMNR.START_LOGMNR(STARTTIME => '2015-06-03 11:10:12',ENDTIME => '2015-06-03 11:13:06',OPTIONS => DBMS_LOGMNR.DICT_FROM_ONLINE_CATALOG DBMS_LOGMNR.CONTINUOUS_MINE);
END;
/
(五)典型的LogMiner步骤
一个典型的LogMiner的操作包含如下步骤:
1、进行初始化设置:开启附加日志,设置LogMiner的表空间,设置UTL_FILE_DIR参数的值;
2、提取一个字典:将字典文件提取为Flat File或Redo日志,或者直接使用Online Catalog;
3、指定需要分析的Redo日志文件:利用DBMS_LOGMNR.ADD_LOGFILE来添加日志;
4、开始LogMiner:执行DBMS_LOGMNR.START_LOGMNR来启动LogMiner;
5、查询V$LOGMNR_CONTENTS视图;
6、结束LogMiner:通过执行EXECUTE DBMS_LOGMNR.END_LOGMNR来结束分析。
下面给出一个使用Online Catalog作为数据字典进行日志挖掘的示例:
代码语言:javascript复制SQL> alter session set NLS_DATE_FORMAT='YYYY-MM-DD HH24:mi:ss';
Session altered.
SQL> select member from v$logfile;
MEMBER
---------------------------------------------------
DATA/orclasm/onlinelog/group_3.263.850260263
FRA/orclasm/onlinelog/group_3.259.850260267
DATA/orclasm/onlinelog/group_2.262.850260259
FRA/orclasm/onlinelog/group_2.258.850260263
DATA/orclasm/onlinelog/group_1.261.850260255
FRA/orclasm/onlinelog/group_1.257.850260259
6 rows selected.
SQL> execute dbms_logmnr.add_logfile(' DATA/orclasm/onlinelog/group_1.261.850260255',dbms_logmnr.new);
PL/SQL procedure successfully completed.
SQL> execute dbms_logmnr.add_logfile(' DATA/orclasm/onlinelog/group_2.262.850260259',dbms_logmnr.addfile);
PL/SQL procedure successfully completed.
SQL> execute dbms_logmnr.add_logfile(' DATA/orclasm/onlinelog/group_3.263.850260263',dbms_logmnr.addfile);
PL/SQL procedure successfully completed.
SQL> exec dbms_logmnr.start_logmnr(options=>dbms_logmnr.dict_from_online_catalog dbms_logmnr.committed_data_only);
PL/SQL procedure successfully completed.
SQL> select sql_redo,sql_undo from v$logmnr_contents where table_name='T' and OPERATION='INSERT';
SQL_REDO SQL_UNDO
------------------------------------------- ------------------------------------------------------------------------
insert into "LHR"."T"("ID") values ('1'); delete from "LHR"."T" where "ID" = '1' and ROWID = 'AAAaN7AAEAAAnhjAAA';
insert into "LHR"."T"("ID") values ('2'); delete from "LHR"."T" where "ID" = '2' and ROWID = 'AAAaN7AAEAAAnhjAAB';
& 说明:
有关LogMiner的更多内容可以参考我的BLOG:http://blog.itpub.net/26736162/viewspace-2141148/