很早以前就碰到这个问题,一直以为是由于没有设置FORCE_LOGGING的问题,今天才发现不是这个问题。
问题起源是在10g的版本上使用LOGMNR找不到刚刚执行的DML操作:
SQL> SELECT GROUP#, SEQUENCE#, STATUS FROM V$LOG;
GROUP# SEQUENCE# STATUS
xH/l
O&a5l"Z f0---------- ---------- ----------------
G2i!t h-N5X,]0 1 245 INACTIVEITPUB个人空间"h2rp"d'Zr4C
2 246 INACTIVEITPUB个人空间!bs.s)^%E!DFOp
3 247 CURRENT
SQL> SELECT GROUP#, MEMBER FROM V$LOGFILE;
GROUP# MEMBERITPUB个人空间8]2s6r(x[B]7oI
---------- --------------------------------------------------
4Cg}8mc'j K_"G:_0 3 E:\ORACLE\ORADATA\YTK102\REDO03.LOGITPUB个人空间u
P/C zI3Yjo$](U
2 E:\ORACLE\ORADATA\YTK102\REDO02.LOGITPUB个人空间5s5Qa6k/v
1 E:\ORACLE\ORADATA\YTK102\REDO01.LOG
SQL> DROP TABLE T PURGE;
表已删除。
SQL> CREATE TABLE T (ID NUMBER);
表已创建。
SQL> INSERT INTO T VALUES (1);
已创建1行。
SQL> COMMIT;
提交完成。
SQL> ALTER SYSTEM SWITCH LOGFILE;
系统已更改。
SQL> EXEC SYS.DBMS_LOGMNR.ADD_LOGFILE('E:\ORACLE\ORADATA\YTK102\REDO03.LOG', SYS.DBMS_LOGMNR.NEW)
PL/SQL过程已成功完成。
SQL> EXEC SYS.DBMS_LOGMNR.START_LOGMNR(OPTIONS => SYS.DBMS_LOGMNR.DICT_FROM_ONLINE_CATALOG)
PL/SQL过程已成功完成。
SQL> SELECT SQL_REDO FROM V$LOGMNR_CONTENTS WHERE SEG_OWNER = USER AND TABLE_NAME = 'T';
SQL_REDOITPUB个人空间Xo$fZj
------------------------------------------------------------------
FrV!@AL9lO0CREATE TABLE T (ID NUMBER);
SQL> EXEC SYS.DBMS_LOGMNR.END_LOGMNR
PL/SQL过程已成功完成。
SQL> SELECT * FROM V$VERSION;
BANNERITPUB个人空间.FK0c^R:?\
----------------------------------------------------------------ITPUB个人空间u?|H
~};iB{0D#J
Oracle Database10gEnterprise Edition Release10.2.0.1.0 - ProdITPUB个人空间#O8iN4UQ }+QXG}Z
PL/SQL Release 10.2.0.1.0 - Production
V x%J"t_&~ Z0CORE 10.2.0.1.0 Production
rnV2OX-u?3|~;`e0TNS for 32-bit Windows: Version 10.2.0.1.0 - ProductionITPUB个人空间Yv6S]Q2OZ
NLSRTL Version 10.2.0.1.0 - Production
本来一直是认为是没有设置FORCE_LOGGING,导致部分记录没有在REDO文件中被记录,结果查询V$DATABASE确发现当前正是FORCE LOGGING状态:
SQL> SELECT FORCE_LOGGING FROM V$DATABASE;
FOR
-}G5E6o7aZ9U;O7a0---ITPUB个人空间-d$O[4ysG*J?
YES
同样的问题从没有在9i上发生过,说明应该是Oracle10g的某些改变导致了问题的产生。
查询了metalink,Oracle在文档Doc ID: Note:291574.1中对这个问题进行了详细说明,如果希望LOGMNR可以得到记录,应该设置SUPPLEMENTAL LOG DATA PRIMARY KEY和UNIQUE INDEX,这样Oracle才能确保LOGMNR可以获取SQL语句:
SQL> SELECT SUPPLEMENTAL_LOG_DATA_PK, SUPPLEMENTAL_LOG_DATA_UI FROM V$DATABASE;
SUP SUPITPUB个人空间'c?)`
h0\+[E.A
--- ---
NL | Om)Xd+|P0NO NO
SQL> ALTER DATABASE ADD SUPPLEMENTAL LOG DATA (PRIMARY KEY, UNIQUE INDEX) COLUMNS;
数据库已更改。
SQL> SELECT SUPPLEMENTAL_LOG_DATA_PK, SUPPLEMENTAL_LOG_DATA_UI FROM V$DATABASE;
SUP SUP
T,K3dfq)l/N+\I0--- ---ITPUB个人空间&G5Z8s6E p/z
YES YES
SQL> SELECT GROUP#, SEQUENCE#, STATUS FROM V$LOG;
GROUP# SEQUENCE# STATUSITPUB个人空间Ox$t)p#e
---------- ---------- ----------------
2v%?ych}2X0 1 248 CURRENT
'Q/b0LzX l0 2 246 INACTIVEITPUB个人空间1I fw3\{wG*O
3 247 INACTIVE
SQL> DROP TABLE T PURGE;
表已删除。
SQL> CREATE TABLE T (ID NUMBER);
表已创建。
SQL> INSERT INTO T VALUES (1);
已创建1行。
SQL> COMMIT;
提交完成。
SQL> ALTER SYSTEM SWITCH LOGFILE;
系统已更改。
SQL> EXEC SYS.DBMS_LOGMNR.ADD_LOGFILE('E:\ORACLE\ORADATA\YTK102\REDO01.LOG', SYS.DBMS_LOGMNR.NEW)
PL/SQL过程已成功完成。
SQL> EXEC SYS.DBMS_LOGMNR.START_LOGMNR(OPTIONS => SYS.DBMS_LOGMNR.DICT_FROM_ONLINE_CATALOG)
PL/SQL过程已成功完成。
SQL> SELECT SQL_REDO FROM V$LOGMNR_CONTENTS WHERE SEG_OWNER = USER AND TABLE_NAME = 'T';
SQL_REDOITPUB个人空间'c;W,S~&U8H
----------------------------------------------------------------------------------
k;Q@O)r"R6T4\w^0DROP TABLE T PURGE;ITPUB个人空间g:{qd;j:dX4Q
D
CREATE TABLE T (ID NUMBER);ITPUB个人空间VZ]GE5qf3K
insert into "YANGTK"."T"("ID") values ('1');
SQL> EXEC SYS.DBMS_LOGMNR.END_LOGMNR
PL/SQL过程已成功完成。
可以看到,在10g中默认情况下LOGMNR已经不是一个可靠的数据获取的方式,希望通过这种方式获取丢失数据,则需要提前设置SUPPLEMENTAL LOG DATA。