Sunteți pe pagina 1din 8

Using Oracle LogMiner ===================== LogMiner allows you to look inside your redo logs and review DML

and DDL stateme nts. Setting up LogMiner Check if you have configured a directory where Oracle can read and write (this a re not the directories created with CREATE DIRECTORY): SQL> show parameter utl_file_dir NAME TYPE VALUE ------------------------------------ ----------- ----------------------------utl_file_dir string Value is empty? Set Oracle parameter UTL_FILE_DIR in (server) parameter file, bo unce the instance and run utlfile.sql: $ sqlplus / as sysdba SQL> SQL> SQL> SQL> alter system set utl_file_dir = '/tmp' scope = spfile; shutdown startup @?/rdmbs/admin/utlfile

Next you need to setup LogMiner dictionary four your instance to map object ids to names and provide human-readable insight to the logs if you don t build it you see something like this: SQL> select sql_redo from v$logmnr_contents; SQL_REDO ------------------------------------------------------------------------------set transaction read write; insert into UNKNOWN.Objn:25128(Col[1]) values (HEXTORAW('c102')); commit; instead of: SQL> select sql_redo from v$logmnr_contents; SQL_REDO ------------------------------------------------------------------------------set transaction read write; insert into test1 values (1); commit; Build the dictionary with DBMS_LOGMNR_D.BUILD: SQL> exec dbms_logmnr_d.build(dictionary_filename => 'dictionary.ora', dicti onary_location => '/tmp'); PL/SQL procedure successfully completed. LogMiner views What data dictionary views do we have got?

SQL> select view_name from all_views where view_name like '%LOGMNR%'; VIEW_NAME -----------------------------V_$LOGMNR_CALLBACK V_$LOGMNR_CONTENTS V_$LOGMNR_DICTIONARY V_$LOGMNR_DICTIONARY_LOAD V_$LOGMNR_LATCH V_$LOGMNR_LOGFILE V_$LOGMNR_LOGS V_$LOGMNR_PARAMETERS V_$LOGMNR_PROCESS V_$LOGMNR_REGION V_$LOGMNR_SESSION V_$LOGMNR_STATS V_$LOGMNR_TRANSACTION DBA_LOGMNR_LOG DBA_LOGMNR_PURGED_LOG DBA_LOGMNR_SESSION 13 rows selected. I will just use V$LOGMNR_CONTENTS in this blog entry. See V$LOGMNR_CONTENTS in O racle Database Reference 11g Release 2 (11.2) for an explanation of all columns in this view. A simple session with LogMiner Take a look at the available logfile by querying V$LOGFILE and V$ARCHIVED_LOG: SQL> select sequence#,name,status,deleted from v$archived_log; SEQUENCE# NAME S DEL ---------- -------------------------------------------------------------------------- - --7 /u04/app/oracle/orafra/PROD/archivelog/2011_05_11/o1_mf_1_7_6wnn7 thl_.arc A NO 8 /u04/app/oracle/orafra/PROD/archivelog/2011_05_11/o1_mf_1_8_6wnt0 o61_.arc A NO 9 /u04/app/oracle/orafra/PROD/archivelog/2011_05_11/o1_mf_1_9_6wnt1 fr5_.arc A NO [...] 40 /u04/app/oracle/orafra/PROD/archivelog/2011_05_13/o1_mf_1_40_6wsq ps23_.arc A NO 41 /u04/app/oracle/orafra/PROD/archivelog/2011_05_13/o1_mf_1_41_6wsq sccn_.arc A NO 42 /u04/app/oracle/orafra/PROD/archivelog/2011_05_13/o1_mf_1_42_6wsq sgxv_.arc A NO SQL> select f.group#,l.sequence#,f.member from v$logfile f inner join v$log l on f.group# = l.group#; GROUP# SEQUENCE# ---------- ------------------------1 43 o_.log 1 43 MEMBER -----------------------------------------------------/u02/app/oracle/oradata/PROD/onlinelog/o1_mf_1_6wlfqxh /u02/app/oracle/oradata/PROD/onlinelog/o1_mf_1_6wlfqxw

w_.log 2 0_.log 2 y_.log We can see that logs from sequence #7 up to #42 are archived and they are NOT DE Leted, so they are available for analysis. The actual log sequence #43 is availa ble in redo log group #1. Start LogMiner At first add the logfiles you want to analyze, take care: first logfile is added with option DBMS_LOGMNR.NEW, others with DBMS_LOGMNR.ADDFILE. I want to analyze the last four log sequences (3 archived, 1 online log sequence): SQL> exec dbms_logmnr.add_logfile(logfilename => '/u04/app/oracle/orafra/PRO D/archivelog/2011_05_13/o1_mf_1_40_6wsqps23_.arc', 2 options => dbms_logmnr.new); PL/SQL procedure successfully completed. SQL> exec dbms_logmnr.add_logfile(logfilename => '/u04/app/oracle/orafra/PRO D/archivelog/2011_05_13/o1_mf_1_41_6wsqsccn_.arc', 2 options => dbms_logmnr.addfile); PL/SQL procedure successfully completed. SQL> exec dbms_logmnr.add_logfile(logfilename => '/u04/app/oracle/orafra/PRO D/archivelog/2011_05_13/o1_mf_1_42_6wsqsgxv_.arc', 2 options => dbms_logmnr.addfile); PL/SQL procedure successfully completed. SQL> exec dbms_logmnr.add_logfile(logfilename => '/u02/app/oracle/oradata/PR OD/onlinelog/o1_mf_1_6wlfqxho_.log', 2 options => dbms_logmnr.addfile); PL/SQL procedure successfully completed. Start a session using the previously created dictionary logfile for the instance : SQL> exec dbms_logmnr.start_logmnr(dictfilename => '/tmp/dictionary.ora'); SQL> select scn, sql_redo from v$logmnr_contents where ... ; Alternatively you can start a session and give some contraints on time or SCN: SQL> exec dbms_logmnr.start_logmnr(dictfilename => '/tmp/dictionary.ora' 2 , starttime => to_date('01-Feb-2011 08:00:00', 'DD-MON-YYYY HH:MI:SS') 3 , endtime => to_date('01-Feb-2011 10:00:00', 'DD-MON-YYYY HH:MI:SS')); LogMiner shows only DML statements and transaction control from redo and undo. D DL (i.e. DROP TABLE) is a DML on data dictionary items! To find DDL statements y ou have to query for DML against SYS.TAB$ for example. SQL> SQL> SQL> SQL> column seg_name format a25 trunc col seg_name format a10 col seg_owner format a20 col table_space format a15 42 /u02/app/oracle/oradata/PROD/onlinelog/o1_mf_2_6wlfr21 42 /u02/app/oracle/oradata/PROD/onlinelog/o1_mf_2_6wlfr06

SQL> col operation format a11 SQL> select seg_name , seg_type , seg_owner , table_name , table_space , operation , scn from v$logmnr_contents where operation != 'INTERNAL' and seg_name in ('COL$','OBJ$','TAB$') group by seg_name , seg_type , seg_owner , table_name , table_space , operation , scn order by scn; SEG_NAME SEG_TYPE SEG_OWNER TABLE_SPACE OPERATION SCN ---------- ---------- ---------------------------------- ----------- ---------OBJ$ 2 SYS SYSTEM INSERT 407518 OBJ$ 2 SYS SYSTEM UPDATE 407521 OBJ$ 2 SYS SYSTEM INSERT 407524 OBJ$ 2 SYS SYSTEM INSERT 407528 OBJ$ 2 SYS SYSTEM UPDATE 407535 OBJ$ 2 SYS SYSTEM UPDATE 407539 OBJ$ 2 SYS SYSTEM UPDATE 407543 OBJ$ 2 SYS SYSTEM INSERT 407594 OBJ$ 2 SYS SYSTEM UPDATE 407596 OBJ$ 2 SYS SYSTEM UPDATE 407598 OBJ$ 2 SYS SYSTEM UPDATE 407600 TABLE_NAME -------------------------------OBJ$ OBJ$ OBJ$ OBJ$ OBJ$ OBJ$ OBJ$ OBJ$ OBJ$ OBJ$ OBJ$

End your session with DBMS_LOGMNR.END_LOGMNR or just start a new one with DBMS_L OGMNR.START_LOGMNR. SQL> exec dbms_logmnr.end_logmnr; I can t find a dropped table with LogMiner Maybe you re using the Flashback feature and the table was moved into recycle bin:

SQL> show parameter flashback NAME TYPE VALUE ------------------------------------ ----------- ----------------------------db_flashback_retention_target SQL> show parameter recyclebin NAME TYPE VALUE ------------------------------------ ----------- ----------------------------recyclebin string on The recyclebin is turned on. So dropped tables will not be dropped, they are ren amed: SQL> show recyclebin ORIGINAL NAME RECYCLEBIN NAME OBJECT TYPE DROP TIME ---------------- ------------------------------ ------------ -----------------TEST 3:36 Recover it using the FLASHBACK TABLE command: SQL> flashback table ttt to before drop; Finding a log sequence by time To find certain statements you need to locate the needed logfile(s). At first yo u may know the time when a statement was issued. The data dictionary views V$ARC HVIED_LOG and V$BACKUP_REDOLOG give a lot of information on what log sequence an d SCNs (system change numbers) belong to which time frame: SQL> SQL> SQL> SQL> [...] NAME SEQU ENCE# FIRST_CHANGE# FIRST_TIME ---------------------------------------------------------------------- --------- ------------- -------------35 36 37 38 39 270339 15.02.11 15:04 270523 15.02.11 15:08 275453 15.02.11 15:26 278957 15.02.11 15:28 283483 15.02.11 16:37 set linesize 132 col name format a70 alter session set nls_date_format = 'DD.MM.YY HH24:MI'; select name, sequence#, first_change#, first_time from v$archived_log; BIN$oyQvIAiLn73gQCi8yGgVVw==$0 TABLE 2011-05-13:09:2 integer 1440

40 283681 15.02.11 16:43 /u02/app/oracle/fra/AOC/archivelog/2011_02_16/o1_mf_1_41_6or9x348_.arc

41 283705 15.02.11 16:43 /u02/app/oracle/fra/AOC/archivelog/2011_02_16/o1_mf_1_42_6orb7r4w_.arc 42 337380 16.02.11 20:38 /u02/app/oracle/fra/AOC/archivelog/2011_02_17/o1_mf_1_43_6otb8y65_.arc 43 337619 16.02.11 20:43 /u02/app/oracle/fra/AOC/archivelog/2011_02_18/o1_mf_1_44_6ox4wn28_.arc 44 397223 17.02.11 14:56 /u02/app/oracle/fra/AOC/archivelog/2011_02_18/o1_mf_1_45_6ox4xqth_.arc 45 450667 18.02.11 16:43 39 rows selected. This query shows us that log sequences from 41 to 45 are available on disk in th e FRA (flash recovery area). Our online redo logs are: SQL> SQL> SQL> SQL> er from v$log l inner join v$logfile f on l.group# = f.group# group by l.group#, sequence#, first_change#, first_time; GROUP# SEQUENCE# FIRST_CHANGE# ---------- ---------- ---------------------------------------------2 46 450705 OC/onlinelog/o1_mf_2_6om6m588_.log 1 45 450667 OC/onlinelog/o1_mf_1_6om6m1tr_.log FIRST_TIME MEMBER ----------------- --------------------18.02.11 16:43:51 /u02/app/oracle/fra/A 18.02.11 16:43:15 /u02/app/oracle/fra/A set linesize 132 col member format a70 alter session set nls_date_format = 'DD.MM.YY HH24:MI:SS'; select l.group#, sequence#, first_change#, first_time, min(member) memb

Use LogMiner like shown above to take a look into the log. Now I want to see the statements, look at the column SQL_REDO in V$LOGMNR_CONTENTS: SQL> select sql_redo from v$logmnr_contents where scn=407518; SQL_REDO -------------------------------------------------------------------------------------------------------------------------commit; set transaction read write; insert into "SYS"."SCHEDULER$_EVENT_LOG"("LOG_ID","LOG_DATE","TYPE#","NAME", "OWNER","CLASS_ID","OPERATION","STATUS","USER_NAME","CLI ENT_ID","GUID","DBID","FLAGS","CREDENTIAL","DESTINATION","ADDITIONAL_INFO") values ('99',TO_TIMESTAMP_TZ('12-MAY-11 10.00.06.423812 PM +02:00'),'66','DRA_REEVALUATE_OPEN_FAILURES','SYS','12166','RUN','SUCCEED ED',NULL,NULL,NULL,NULL,'0',NULL,NULL,NULL); insert into "SYS"."SCHEDULER$_JOB_RUN_DETAILS"("LOG_ID","LOG_DATE","REQ_STAR T_DATE","START_DATE","RUN_DURATION","INSTANCE_ID","SESSI ON_ID","SLAVE_PID","CPU_USED","ERROR#","ADDITIONAL_INFO","CREDENTIAL","DESTI NATION") values ('99',TO_TIMESTAMP_TZ('12-MAY-11 10.00.0 6.536282 PM +02:00'),NULL,TO_TIMESTAMP_TZ('12-MAY-11 10.00.03.047298 PM EURO PE/VIENNA'),TO_DSINTERVAL('+000 00:00:03'),'1','160,747' ,'22112',TO_DSINTERVAL('+000 00:00:00.08'),'0',NULL,NULL,NULL); insert into "SYS"."OBJ$"("OBJ#","DATAOBJ#","OWNER#","NAME","NAMESPACE","SUBN AME","TYPE#","CTIME","MTIME","STIME","STATUS","REMOTEOWN ER","LINKNAME","FLAGS","OID$","SPARE1","SPARE2","SPARE3","SPARE4","SPARE5"," SPARE6") values ('13098',NULL,'0','ORA$AT_OS_OPT_SY_7','

1',NULL,'66',TO_DATE('12-MAY-11', 'DD-MON-RR'),TO_DATE('12-MAY-11', 'DD-MONRR'),TO_DATE('12-MAY-11', 'DD-MON-RR'),'1',NULL,NULL,'0' ,NULL,'6','65535','0',NULL,NULL,NULL); If you need to backout that change, query the column SQL_UNDO: SQL_UNDO -------------------------------------------------------------------------------------------------------------------------delete from "SYS"."SCHEDULER$_EVENT_LOG" where "LOG_ID" = '99' and "LOG_DATE " = TO_TIMESTAMP_TZ('12-MAY-11 10.00.06.423812 PM +02:00 ') and "TYPE#" = '66' and "NAME" = 'DRA_REEVALUATE_OPEN_FAILURES' and "OWNER " = 'SYS' and "CLASS_ID" = '12166' and "OPERATION" = 'RU N' and "STATUS" = 'SUCCEEDED' and "USER_NAME" IS NULL and "CLIENT_ID" IS NUL L and "GUID" IS NULL and "DBID" IS NULL and "FLAGS" = '0 ' and "CREDENTIAL" IS NULL and "DESTINATION" IS NULL and ROWID = 'AAABbfAACA AAAzOAAO'; delete from "SYS"."SCHEDULER$_JOB_RUN_DETAILS" where "LOG_ID" = '99' and "LO G_DATE" = TO_TIMESTAMP_TZ('12-MAY-11 10.00.06.536282 PM +02:00') and "REQ_START_DATE" IS NULL and "START_DATE" = TO_TIMESTAMP_TZ('12 -MAY-11 10.00.03.047298 PM EUROPE/VIENNA') and "RUN_DURA TION" = TO_DSINTERVAL('+000 00:00:03') and "INSTANCE_ID" = '1' and "SESSION_ ID" = '160,747' and "SLAVE_PID" = '22112' and "CPU_USED" = TO_DSINTERVAL('+000 00:00:00.08') and "ERROR#" = '0' and "ADDITIONAL_INFO " IS NULL and "CREDENTIAL" IS NULL and "DESTINATION" IS NULL and ROWID = 'AAABbjAACAAAAztAAI'; delete from "SYS"."OBJ$" where "OBJ#" = '13098' and "DATAOBJ#" IS NULL and " OWNER#" = '0' and "NAME" = 'ORA$AT_OS_OPT_SY_7' and "NAM ESPACE" = '1' and "SUBNAME" IS NULL and "TYPE#" = '66' and "CTIME" = TO_DATE ('12-MAY-11', 'DD-MON-RR') and "MTIME" = TO_DATE('12-MAY -11', 'DD-MON-RR') and "STIME" = TO_DATE('12-MAY-11', 'DD-MON-RR') and "STAT US" = '1' and "REMOTEOWNER" IS NULL and "LINKNAME" IS NU LL and "FLAGS" = '0' and "OID$" IS NULL and "SPARE1" = '6' and "SPARE2" = '6 5535' and "SPARE3" = '0' and "SPARE4" IS NULL and "SPARE 5" IS NULL and "SPARE6" IS NULL and ROWID = 'AAAAASAABAAAEg1AAL'; Optimize It s best to create a (temporary) table of the contents of v$logmnr_contents to sa ve time and performance when querying the logs: SQL> create table mylog as select ... from v$logmnr_contents; Take care It s very important to end the LogMiner session with DBMS_LOGMNR.END_LOGMNR, as yo u will get an ORA-600 error when logging off: SQL> exec dbms_logmnr.end_logmnr(); Trying to use LogMiner concurrently from another session will give a ORA-01306: dbms_logmnr.start_logmnr() must be invoked before selecting from v$logmnr_conten ts. See MOS Note 62508.1 The LogMiner Utility for details. Recover the database using RMAN After finding the correct log sequence or SCN use it with RMAN s UNTIL-clause like

this: RMAN> recover database until scn 220123; or RMAN> recover database until logseq 43;

S-ar putea să vă placă și