10g utilities:How to use LogMiner I

对数据库做不完全恢复的时候,如果我们能够精确的定位到出错的时间点的话,那么,我们可以在很大的程度上一次性地保证不完全恢复成功。所以,问题也就是我们应该怎么能够准确定位这个人为错误(如误删除表,错误的提交DML)发生的时间?接下来,要跟大家分享一下关于10g里LogMiner这个“日志挖掘器”的用法,也就是,在Oracle 10g版本的数据库,应该怎么使用LogMiner: 首先:简单介绍一下LogMiner工具。LogMiner 是Oracle公司从产品8i以后提供的一个非常有实用价值的分析工具,使用该工具可以轻松获得Oracle Online redo logs或者Archived logs日志文件中的具体内容。日志文件中记录了所有对数据库的数据块儿进行过改变的操作,而Logminer正是可以挖掘日志文件的利器。 其次:该如何使用Logminer?在早期的数据库版本里,LogMiner在默认情况下,并没有安装,需要手工的以SYSDBA身份去执行$ORACLE_HOME/rdbms/admin/dbmslm.sql以及$ORACLE_HOME/rdbms/admin/dbmslmd.sql这两个脚本。前者是创建DBMS_LOGMNR package,后者用于创建DBMS_LOGMNR_D这个包。在10g版本的数据库,这两个PL/SQL 包默认已经创建,我们就无须再去执行那两个脚本,可以直接对其调用。 然后:需要说明的一点,在Oracle 10g数据库版本里面,默认情况下,联机日志文件记录的内容并非提供任何的Supplemental logging,也就是说默认情况下使用LogMiner只能看到DDL操作。要想看到DML操作的话,在DML操作产生新的日志记录之前我们要启用最低的Supplemental logging,而启用这一特性又分为在数据库级别以及表级别,以下简单演示在全库级别启用最低Supplemental logging: 确认当前数据库Supplemental logging:

SQL> select supplemental_log_data_min from v$database;
SUPPLEME
--------
NO

启用Supplemental logging,以便可以通过LogMiner看到日志文件中记录的关于DML操作的相关信息:

SQL> alter database add supplemental log data;
Database altered.
SQL> select supplemental_log_data_min from v$database;
SUPPLEME
--------
YES

日志“挖掘"结束,可以禁用Supplemental logging:

SQL> alter database drop supplemental log data;
Database altered.

接下来:该说说具体使用LogMiner的方法了: 使用方法1: 1.1确认数据库当前的日志文件信息:

SQL> select * from v$log;
    GROUP#    THREAD#  SEQUENCE#      BYTES    MEMBERS ARC STATUS           FIRST_CHANGE# FIRST_TIM
---------- ---------- ---------- ---------- ---------- --- ---------------- ------------- ---------
         1          1          5   52428800          1 YES INACTIVE                674382 16-MAY-10
         2          1          4   52428800          1 YES INACTIVE                660045 15-MAY-10
         3          1          6   52428800          1 NO  CURRENT                 691344 20-MAY-10
SQL> select * from v$logfile;
    GROUP# STATUS  TYPE    MEMBER                                   IS_
---------- ------- ------- ---------------------------------------- ---
         3         ONLINE  /u01/app/oradata/helen/redo03.log        NO
         2         ONLINE  /u01/app/oradata/helen/redo02.log        NO
         1         ONLINE  /u01/app/oradata/helen/redo01.log        NO

1.2从上面的结果可以确定当前数据库使用的是第3组日志,其对应的日志文件成员为/u01/app/oradata/helen/redo03.log ,也就是说,当前情况下,所有接下来对数据库的操作都将记录在第3个日志组所对应文件成员中,直到该日志组被写满为止。把该组的日志成员添加到LogMiner的"挖掘"范围之内:

SQL> exec dbms_logmnr.add_logfile
(logfilename=>'/u01/app/oradata/helen/redo03.log',
options=>dbms_logmnr.new);
PL/SQL procedure successfully completed.

可以通过v$logmnr_logs数据字典表验证:

SQL> select filename from v$logmnr_logs;
FILENAME
----------------------------------------
/u01/app/oradata/helen/redo03.log

想继续添加其他日志文件成员进来,只需重新执行上述PL/SQL package,把对应的参数修改为新的日志文件成员名称,并且把new以addfile取代。删除对某个日志文件成员的挖掘,只需以removefile取代new之。 1.3执行LogMiner:

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

1.4开启另外一个会话,而且一定是新开第二个会话,不能跟刚才执行的调用Logminer在同一个会话,并且执行DML操作:

SQL> conn hr/hr;
Connected.
SQL> insert into test values(20);
1 row created.
SQL> insert into test values(21);
1 row created.
SQL> delete from test where id=21;
1 row deleted.
SQL>

1.5这时HR执行的操作已经被记录到日志文件里了,再切回到第一个会话,执行下述操作:

 SQL> select timestamp,table_name,sql_redo,sql_undo,operation
  2  from v$logmnr_contents
  3  where username='HR'

TIMESTAMP           TABLE SQL_REDO                                      SQL_UNDO                                 OPERATIO
------------------- ----- --------------------------------------------- ---------------------------------------- --------
2010/05/20 01:56:33       set transaction read write;                                                            START
2010/05/20 01:56:33 TEST  insert into "HR"."TEST"("ID") values ('20');  delete from "HR"."TEST" where "ID" = '20 INSERT
                                                                        ' and ROWID = 'AAAM39AAEAAAAGNAAA';

2010/05/20 01:56:36 TEST  insert into "HR"."TEST"("ID") values ('21');  delete from "HR"."TEST" where "ID" = '21 INSERT
                                                                        ' and ROWID = 'AAAM39AAEAAAAGNAAB';

2010/05/20 01:56:42 TEST  delete from "HR"."TEST" where "ID" = '21' and insert into "HR"."TEST"("ID") values ('2 DELETE
                           ROWID = 'AAAM39AAEAAAAGNAAB';                1');

1.6显然,我们可以看到准确的有用信息,当然V$logmnr_contents字典表中还可能有我们更为关心的字段,我们可以根据需要自行选取查看。挖掘完成之后,可以显示停止对Logminer工具的调用,也可以断开当前会话隐式停止对Logminer工具的使用,因为V$logmnr_contents表里的内容是存放在当前会话PGA里的。这也是为什么在调用Logminer的时候,其他会话是看不到v$logmnr_contents表里的内容,也解释了在第4步骤中为什么必须新开一个会话的原因。

SQL> exec dbms_logmnr.end_logmnr;
PL/SQL procedure successfully completed.
SQL> select filename from v$logmnr_logs;
no rows selected

关于LogMiner使用的另外一种方法,将在另外一篇日志里同大家齐分享!

发表评论

邮箱地址不会被公开。 必填项已用*标注