深化分析Oracle数据库日志文件

   源头:网海拾贝




作为Oracle DBA,我们偶然偶尔刻必要追踪数据误删除或用户的歹意利用状况,此时我们不光必要查出实行这些利用的数据库账号,还必要晓得利用是由哪台客户端(IP地址等)发出的。针对这些成绩,一个最有效实用而又低成本的体式格局即是分析Oracle数据库的日志文件。本文将就Oracle日志分析身手做深化计议。

一、若何分析即LogMiner解释

从目前来看,分析Oracle日志的唯一体式格局即是运用Oracle公司供应的LogMiner来举办, Oracle数据库的一切更动都记住实日志中,然则原始的日志信息我们根本无法看懂,而LogMiner即是让我们看懂日志信息的对象。从这一点上看,它和tkprof差不久不多,一个是用来分析日志信息,一个则是格局化跟踪文件。议决对日志的分析我们可以完成下面的目的:

1、查明数据库的逻辑更动;

2、侦探并改正用户的误利用;

3、实行预先审计;

4、实行转变分析。

不光如斯,日志中记载的信息还包罗:数据库的更动历史、更动类型(INSERT、UPDATE、DELETE、DDL等)、更动对应的SCN号、以及实行这些利用的用户信息等,LogMiner在分析日志时,将重构等价的SQL语句和UNDO语句(区分记住实V$LOGMNR_CONTENTS视图的SQL_REDO和SQL_UNDO中)。这里必要细致的是等价语句,而并非原始SQL语句,比方:我们最后实行的是“delete a where c1 <>'cyx';”,而LogMiner重构的是等价的6条DELETE语句。所以我们应该熟悉到V$LOGMNR_CONTENTS视图中体现的并非是原版的梦想,从数据库角度来讲这是很容易相识的,它记载的是元利用,由于异样是“delete a where c1 <>'cyx';”语句,在分譬喻的情况中,实践删除的记载数可以各不相反,是以记载如许的语句实践上并没有什么实践意义,LogMiner重构的是在实践状况下转化成元利用的多个单条语句。

另外由于Oracle重做日志中记载的并非原始的对象(如表以及此中的列)称号,而只是它们在Oracle数据库中的内部编号(关于表来说是它们在数据库中的对象ID,而关于表中的列来说,对应的则是该列在表中的排列序号:COL 1, COL 2 等),是觉得了使LogMiner重构出的SQL语句易于识别,我们必要将这些编号转化成响应的称号,这就必要用到数据字典(也就说LogMiner本身是可以不必数据字典的,详见下面的分析进程),LogMiner利用DBMS_LOGMNR_D.BUILD()进程来提取数据字典信息。

LogMiner包罗两个PL/SQL包和几个视图:

1、dbms_logmnr_d包,这个包只包罗一个用于提取数据字典信息的进程,即dbms_logmnr_d.build()进程。

2、dbms_logmnr包,它有三个进程:

add_logfile(name varchar2, options number) - 用来添加/删除用于分析的日志文件;

start_logmnr(start_scn number, end_scn number, start_time number,end_time number, dictfilename varchar2, options number) - 用来开启日志分析,同时确定分析的工夫/SCN窗口以及确认能否运用提取出来的数据字典信息。

end_logmnr() - 用来中断分析会话,它将收受接管LogMiner所占用的内存。

与LogMiner关连的数据字典。

1、v$logmnr_dictionary,LogMiner可以运用的数据字典信息,因logmnr可以有多个字典文件,该视图用于体现这方面信息。

2、v$logmnr_parameters,以后LogMiner所设定的参数信息。

3、v$logmnr_logs,以后用于分析的日志列表。

4、v$logmnr_contents,日志分析成绩。

二、Oracle9i LogMiner的加强:

1、支撑更多半据/存储类型:链接/迁徙行、CLUSTER表利用、DIRECT PATH拔出以及DDL利用。在V$LOGMNR_CONTENTS的SQL_REDO中可以看到DDL利用的原句(CREATE USER除外,此中的暗码将以加密的形式呈现,而不是原始暗码)。如果TX_AUDITING初始化参数设为TRUE,则一切利用的数据库账号将被记载。

2、提取和运用数据字典的选项:现在数据字典不光可以提取到一个内部文件中,还可以直接提取到重做日志流中,它在日志流中供应了利用当时');的数据字典快照,如许就可以完成离线分析。

3、容许对DML利用按事宜举办分组:可以在START_LOGMNR()中设置COMMITTED_DATA_ONLY选项,完成对DML利用的分组,如许将按SCN的递次前往已经提交的事宜。

4、支撑SCHEMA的转变:在数据库掀开的状况下,如果运用了LogMiner的DDL_DICT_TRACKING选项,Oracle9i的LogMiner将自动相比最后的日志流和以后体系的数据字典,并前往准确的DDL语句,而且会自动侦探并标记以后数据字典和最后日志流之间的不同,如许即便最后日志流中所触及的表已经被更动或许根本已经不存在,LogMiner异样会前往准确的DDL语句。

5、在日志中记载更多列信息的才气:比方关于UPDATE利用不光会记载被更新行的状况,还可以捕捉更多前影信息。

6、支撑基于数值的盘查:Oracle9i LogMiner在支撑原有基于元数据(利用、对象等)盘查的根基上,初步支撑基于实践触及到的数据的盘查。比方触及一个人为表,现在我们可以很容易地查出员工人为由1000变成2000的原始更新语句,而在之前我们只能选出一切的更新语句。

三、Oracle8i/9i的日志分析进程

LogMiner只需在实例起来的状况下都可以运转,LogMiner运用一个字典文件来完成Oracle内部对象称号的转换,如果没有这个字典文件,则直接体现内部对象编号,比方我们实行下面的语句:

delete from "C"."A" where "C1" = ‘gototop’ and ROWID = 'AAABg1AAFAAABQaAAH';
如果没有字典文件,LogMiner分析出来的成绩将是:
delete from "UNKNOWN"."OBJ# 6197" where "COL 1" = HEXTORAW('d6a7d4ae') and ROWID
 = 'AAABg1AAFAAABQaAAH';



如果想要运用字典文件,数据库至多应该出于MOUNT状况。然后实行dbms_logmnr_d.build进程将数据字典信息提取到一个内部文件中。下面是细致分析步伐:

1、确认设置了初始化参数:UTL_FILE_DIR,并确认Oracle对改目录拥有读写权限,然后启动实例。示例中UTL_FILE_DIR参数如下:

SQL> show parameter utl
NAME                         TYPE        VALUE
------------------------ ----------- ------------------------------
utl_file_dir                 string      /data6/cyx/logmnr



这个目录主要用于存放dbms_logmnr_d.build进程所发生的字典信息文件,如果不必这个,则可以不设,也就跳过下面一步。

2、天生字典信息文件:

exec dbms_logmnr_d.build(dictionary_filename =>'
dic.ora',dictionary_location => '/data6/cyx/logmnr');



此中dictionary_location指的是字典信息文件的存放职位地方,它必须完全成亲UTL_FILE_DIR的值,比方:假定UTL_FILE_DIR=/data6/cyx/logmnr/,则下面这条语句会蜕化,只由于UTL_FILE_DIR背面多了一个“/”,而在良多另外中心对这一“/”是不敏感的。

dictionary_filename指的是放于字典信息文件的名字,可以肆意取。虽然我们也可以不明确光鲜明显写出这两个选项,即写成:

exec dbms_logmnr_d.build('dic.ora','/data6/cyx/logmnr');

如果你第一步的参数没有设,而直接初步这一步,Oracle会报下面的错误:

ERROR at line 1:
ORA-01308: initialization parameter utl_file_dir is not set
ORA-06512: at "SYS.DBMS_LOGMNR_D", line 923
ORA-06512: at "SYS.DBMS_LOGMNR_D", line 1938
ORA-06512: at line 1



必要细致的是,在oracle817 for Windows版中会呈现以下错误:

14:26:05 SQL> execute dbms_logmnr_d.build('oradict.ora','c:oracleadminoralog');
BEGIN dbms_logmnr_d.build('oradict.ora','c:oracleadminoralog'); END;
*
ERROR at line 1:
ORA-06532: Subscript outside of limit
ORA-06512: at "SYS.DBMS_LOGMNR_D", line 793
ORA-06512: at line 1



处置法子:

编辑"$ORACLE_HOME/rdbms/admindbmslmd.sql"文件,把此中的
TYPE col_desc_array IS VARRAY(513) OF col_description;
改成:
TYPE col_desc_array IS VARRAY(700) OF col_description;



生存生活文件,然后实行一遍这个剧本:

15:09:06 SQL> @c:oracleora81rdbmsadmindbmslmd.sql
Package created.
Package body created.
No errors.
Grant succeeded.



然后重新编译DBMS_LOGMNR_D包:

15:09:51 SQL> alter package DBMS_LOGMNR_D compile body;
Package body altered.
之后重新实行dbms_logmnr_d.build即可:
15:10:06 SQL> execute dbms_logmnr_d.build('oradict.ora','c:oracleadminoralog');
PL/SQL procedure successfully completed.



3、添加必要分析的日志文件

SQL>exec dbms_logmnr.add_logfile( logfilename=>'
/data6/cyx/rac1arch/arch_1_197.arc', options=>dbms_logmnr.new);
PL/SQL procedure successfully completed.



这里的options选项有三个参数可以用:

NEW - 泄露体现创建一个新的日志文件列表

ADDFILE - 泄露体现向这个列表中添加日志文件,如下面的例子

REMOVEFILE - 和addfile相反。

SQL> exec dbms_logmnr.add_logfile( logfilename=>'
/data6/cyx/rac1arch/arch_2_86.arc', options=>dbms_logmnr.addfile);
PL/SQL procedure successfully completed.



4、当你添加了必要分析的日志文件后,我们就可以让LogMiner初步分析了:

SQL> exec dbms_logmnr.start_logmnr(dictfilename=>'/data6/cyx/logmnr/dic.ora');
PL/SQL procedure successfully completed.



如果你没有运用字典信息文件(此时我们只必要启动实例就可以了),那么就不必要跟dictfilename参数:

SQL> exec dbms_logmnr.start_logmnr();
PL/SQL procedure successfully completed.



虽然dbms_logmnr.start_logmnr()进程另有另外几个用于界说分析日志工夫/SCN窗口的参数,它们区分是:

STARTSCN / ENDSCN - 界说分析的起始/终了SCN号,

STARTTIME / ENDTIME - 界说分析的起始/终了工夫。

比方下面的进程将只分析从 '2003-09-21 09:39:00'到'2003-09-21 09:45:00'这段工夫的日志:

SQL> exec dbms_logmnr.start_logmnr(dictfilename=>'/data6/cyx/logmnr/dic.ora' , -
starttime => '2003-09-21 09:39:00',endtime => '2003-09-21 09:45:00');
PL/SQL procedure successfully completed.



下面进程第一行开头的“-”泄露体现转行,如果你在平等行,则不必要。我们可以看到有效日志的工夫戳:

SQL> select distinct timestamp from v$logmnr_contents;
TIMESTAMP
-------------------
2003-09-21 09:40:02
2003-09-21 09:42:39



这里必要细致的是,由于我之前已经设置NL2005-1-31_FORMAT情况变量,所以下面的日期可以直接按这个格局写就行了,如果你没有设,则必要运用to_date函数来转换一下。

SQL> !env|grep NLS
NLS_LANG=american_america.zhs16cgb231280
NL2005-1-31_FORMAT=YYYY-MM-DD HH24:MI:SS
ORA_NLS33=/oracle/oracle9/app/oracle/product/9.2.0/ocommon/nls/admin/data
运用to_date的格局如下:
exec dbms_logmnr.start_logmnr(dictfilename=>'/data6/cyx/logmnr/dic.ora',-
starttime => to_date('2003-09-21 09:39:00','YYYY-MM-DD HH24:MI:SS'),-
endtime => to_date('2003-09-21 09:45:00','YYYY-MM-DD HH24:MI:SS'));



STARTSCN 和ENDSCN参数运用体式格局类似。

5、好了,在下面的进程实行终了之后,我们就可以议决拜访与LogMiner关连的几个视图来提取我们必要的信息了。此中在v$logmnr_logs中可以看到我们以后分析的日志列表,如果数据库有两个实例(即OPS/RAC),在v$logmnr_logs中会有两个分譬喻的THREAD_ID。

而真正的分析成绩是放在v$logmnr_contents中,这外面有良多信息,我们可以按照必要追踪我们感喜好的信息。背面我将独自列出来讲罕有的追踪情况。

6、全数终了之后,我们可以实行dbms_logmnr.end_logmnr进程加入LogMiner分析进程,你也可以直接加入SQL*PLUS,它会自动中断。

四、若何利用LogMiner分析Oracle8的日志文件

虽然说LogMiner是Oracle8i才推出来,但我们异样可以用它来分析Oracle8的日志文件,只不过稍微费事了一点,而且有肯定的限定,下面是细致做法:

我们起首复制Oracle8i的$ORACLE_HOME/rdbms/admin/dbmslmd.sql剧本到Oracle8数据库地点主机的异样目录;这个剧本用于创建dbms_logmnr_d包(细致,Oracle9i中还将创建dbms_logmnr包),如果是8.1.5剧本名字为dbmslogmnrd.sql。然后在Oracle8的数据库上运转这个剧本,之后运用dbms_logmnr_d.build进程创建字典信息文件。现在我们就可以把Oracle8的归档日志连同这个字典信息文件复制到Oracle8i数据库地点的主机上,之后在Oracle8i数据库中从下面分析进程的第三步初步分析Oracle8的日志,不过

dbms_logmnr.start_logmnr()中运用的是Oracle8的字典信息文件。

按照我背面所说的那样,如果不是字典文件,我们则可以直接将Oracle8的归档日志复制到Oracle8i数据库地点主机,然后对它举办分析。

其实这里触及到了一个跨平台运用LogMiner的成绩,笔者做过实行,也可以在Oracle9i中来分析Oracle8i的日志。但这些都是有所限定的,主要体现在:

1、LogMiner所运用的字典文件必须和所分析的日志文件是平等个数据库所发生的,而且该数据库的字符集应和实行LogMiner数据库的相反。这很好相识,如果不是平等个数据库所发生就不存在对应干系了。

2、天生日志的数据库硬件平台和实行LogMiner数据库的硬件平台要求不同,利用体系版本可以不不同。笔者做实行时(如果读者有喜好可以到我网站http://www.ncn.cn上下载实行全进程,由于太长就不放在这里了),所用的两个数据库利用体系都是Tru64 UNIX,但一个是 V5.1A,另一个则是V4.0F。如果利用体系不不同则会呈现下面的错误:

ORA-01284: file /data6/cyx/logmnr/arch_1_163570.arc cannot be opened
ORA-00308: cannot open archived log '/data6/cyx/logmnr/arch_1_163570.arc'
ORA-27048: skgfifi: file header information is invalid
ORA-06512: at "SYS.DBMS_LOGMNR", line 63
ORA-06512: at line 1



五、分析v$logmnr_contents

背面我们已经晓得了LogMiner的分析成绩是放在v$logmnr_contents中,这外面有良多信息,我们可以按照必要追踪我们感喜好的信息。那么我们凡是感喜好的有哪些呢?

1、追踪数据库组织转变状况,即DDL利用,如前所述,这个只需Oracle9i才支撑:

SQL> select timestamp,sql_redo from v$logmnr_contents2 
where upper(sql_redo) like '%CREATE%';
TIMESTAMP
-------------------
SQL_REDO
-------------------------
2003-09-21 10:01:55
create table t (c1 number);



2、追踪用户误利用或歹意利用:

比方我们梦想中有如许需求,有一次我们发现一位员工通历步伐修正了营业数据库信息,把部门德律风的收费类型改成收费了,现在就要求我们从数据库中查出究竟是谁干的这件事?如何查?LogMiner供应了我们分析日志文件的伎俩,此中v$logmnr_contents的SESSION_INFO列包罗了下面的信息:

login_username=NEW_97 
client_info= OS_username=oracle8 Machine_name=phoenix1
 OS_terminal=ttyp3 OS_process_id=8004 OS_program name=sqlplus@phoenix1
 (TNS V1-V3)



虽然此中信息已经良多了,但在我们的营业数据库中,步伐是议决相反的login_username登录数据库的,如许单从下面的信息是很难判另外。

不过我们细致到,由于公司利用效能器不是每全体都有权限在下面写步伐的,普通歹意步伐都是直接议决他自己的PC连到数据库的,这就必要一个准确的定位。IP追踪是我们起首想到的,而且也知足我们的实践要求,由于公司内部IP地址分配是平等经管的,能追踪到IP地址我们就可以准确定位了。但从面的SESSION_INFO中我们并不克不及直接看到IP,不过我们照样有法子的,由于这个SESSION_INFO外面的内容其实此日志从V$SESSION视图里提取的,我们可以在损耗数据库中创建一个追踪客户端IP地址的触发器:

create or replace trigger on_logon_trigger
after logon on database
begin
  dbms_application_info.set_client_info(sys_context('userenv', 'ip_address'));
end;
/



现在,我们就可以在V$SESSION视图的CLIENT_INFO列中看到新登录的客户端IP地址了。那么下面的提出的成绩就可以迎刃而解了。倘使被更新的表名为HMLX,我们就可以议决下面的SQL来找到所需信息:

SQL > select session_info ,sql_redo from v$logmnr_contents 
2 where upper(operation) = 'UPDATE'  and upper(sql_redo) like '%HMLX%'
3 /
SESSION_INFO
-----------------------------------------
SQL_REDO
-----------------------------------------
login_username=C client_info=10.16.98.26 OS_username=sz-xjs-chengyx Machine_name
=GDTELSZ-XJS-CHENGYX
update "C"."HMLX" set "NAME" = 'free' where "NAME" = 'ncn.cn' and ROWID = 'AAABhTAA
FAAABRaAAE';



好了,到此为止,这篇文章就要终理解理睬,如果读者朋侪另有什么疑问,可以登录我的全体网站(www.ncn.cn)来获得最新新闻,也可以议决MSN(gototop_ncn@hotmail.com)直接和我团结。

六、参考资料:

1、Technical White Paper Oracle9i LogMiner

2、Metalink文档:How to Setup LogMiner(文档ID:111886.1)




版权声明: 原创作品,容许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。不然将追究法律责任。

posted @ 2011-03-07 20:08  蓝色的天空III  阅读(537)  评论(0编辑  收藏  举报