yangtingkun
===========================================================
Oracle10G LOGMNR捕获不到记录(一)
===========================================================

很早以前就碰到这个问题,一直以为是由于没有设置FORCE_LOGGING的问题,今天才发现不是这个问题。


问题起源是在10g的版本上使用LOGMNR找不到刚刚执行的DML操作:

SQL> SELECT GROUP#, SEQUENCE#, STATUS FROM V$LOG;

GROUP# SEQUENCE# STATUS
---------- ---------- ----------------
1 245 INACTIVE
2 246 INACTIVE
3 247 CURRENT

SQL> SELECT GROUP#, MEMBER FROM V$LOGFILE;

GROUP# MEMBER
---------- --------------------------------------------------
3 E:ORACLEORADATAYTK102REDO03.LOG
2 E:ORACLEORADATAYTK102REDO02.LOG
1 E:ORACLEORADATAYTK102REDO01.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:ORACLEORADATAYTK102REDO03.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_REDO
------------------------------------------------------------------
CREATE TABLE T (ID NUMBER);

SQL> EXEC SYS.DBMS_LOGMNR.END_LOGMNR

PL/SQL 过程已成功完成。

SQL> SELECT * FROM V$VERSION;

BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod
PL/SQL Release 10.2.0.1.0 - Production
CORE 10.2.0.1.0 Production
TNS for 32-bit Windows: Version 10.2.0.1.0 - Production
NLSRTL Version 10.2.0.1.0 - Production

本来一直是认为是没有设置FORCE_LOGGING,导致部分记录没有在REDO文件中被记录,结果查询V$DATABASE确发现当前正是FORCE LOGGING状态:

SQL> SELECT FORCE_LOGGING FROM V$DATABASE;

FOR
---
YES

同样的问题从没有在9i上发生过,说明应该是Oracle10g的某些改变导致了问题的产生。

查询了metalinkOracle在文档Doc ID: Note:291574.1中对这个问题进行了详细说明,如果希望LOGMNR可以得到记录,应该设置SUPPLEMENTAL LOG DATA PRIMARY KEYUNIQUE INDEX,这样Oracle才能确保LOGMNR可以获取SQL语句:

SQL> SELECT SUPPLEMENTAL_LOG_DATA_PK, SUPPLEMENTAL_LOG_DATA_UI FROM V$DATABASE;

SUP SUP
--- ---
NO 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
--- ---
YES YES

SQL> SELECT GROUP#, SEQUENCE#, STATUS FROM V$LOG;

GROUP# SEQUENCE# STATUS
---------- ---------- ----------------
1 248 CURRENT
2 246 INACTIVE
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:ORACLEORADATAYTK102REDO01.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_REDO
----------------------------------------------------------------------------------
DROP TABLE T PURGE;
CREATE TABLE T (ID NUMBER);
insert into "YANGTK"."T"("ID") values ('1');

SQL> EXEC SYS.DBMS_LOGMNR.END_LOGMNR

PL/SQL 过程已成功完成。

可以看到,在10g中默认情况下LOGMNR已经不是一个可靠的数据获取的方式,希望通过这种方式获取丢失数据,则需要提前设置SUPPLEMENTAL LOG DATA

yangtingkun 发表于:2008.06.22 23:49 ::分类: ( ORACLE ) ::阅读:(1111次) :: 评论 (7)
re: Oracle10G LOGMNR捕获不到记录(一) [回复]

10g的 logmnr文档里就强调了要加supplement logging

棉花糖ONE 评论于: 2008.08.06 15:42
re: Oracle10G LOGMNR捕获不到记录(一) [回复]

嗯,还真没有看过10g的文档,我看完9的以后直接看的11g。

不过文档强调和默认设置的改变还是有区别的。

9i默认是可以获取修改的,而10g默认设置是可能丢失数据的,也就是说,对于dba来说,少了一种默认情况下恢复数据的手段

yangtingkun 评论于: 2008.08.15 15:25
re: Oracle10G LOGMNR捕获不到记录(一) [回复]

--10g特性,不然无法查出dml操作的数据
SELECT SUPPLEMENTAL_LOG_DATA_MIN FROM V$DATABASE;
--如果结果为YES就不需要执行,反之
ALTER DTABASE ADD SUPPLEMENTAL LOG DATA;

此段您的查询还是logical DG的要求(即是否设置不影响logmnr捕获DML的结果,已验证)
SELECT SUPPLEMENTAL_LOG_DATA_PK, SUPPLEMENTAL_LOG_DATA_UI FROM V$DATABASE;

ALTER DATABASE ADD SUPPLEMENTAL LOG DATA (PRIMARY KEY, UNIQUE INDEX) COLUMNS;
&
ALTER DATABASE DROP SUPPLEMENTAL LOG DATA (PRIMARY KEY, UNIQUE INDEX) COLUMNS;
只要执行了ALTER DTABASE ADD SUPPLEMENTAL LOG DATA;
,结果是一样的

以上是我的一点疑问,若不正确请告知

tonie 评论于: 2009.08.17 12:11
re: Oracle10G LOGMNR捕获不到记录(一) [回复]

你的理解没有问题

yangtingkun 评论于: 2009.08.17 21:32
re: Oracle10G LOGMNR捕获不到记录(一) [回复]

杨老师:看了你的文章之后,我做了个测试。我没有启用FORCE LOGGING 和补充日志,竟然也能捕获到。下面是我的测试步骤:

SQL> SELECT * FROM V$VERSION;

BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod
PL/SQL Release 10.2.0.1.0 - Production
CORE 10.2.0.1.0 Production
TNS for 32-bit Windows: Version 10.2.0.1.0 - Production
NLSRTL Version 10.2.0.1.0 - Production

SQL> SELECT FORCING_LOGGING FROM V$DATABASE;
SELECT FORCING_LOGGING FROM V$DATABASE
*
第 1 行出现错误:
ORA-00904: "FORCING_LOGGING": 标识符无效

SQL> SELECT FORCE_LOGGING FROM V$DATABASE;

FOR
---
NO

SQL> SELECT SUPPLEMENTAL_LOG_DATA_MIN,SUPPLEMENTAL_LOG_DATA_PK,SUPPLEMENTAL_LOG_
DATA_UI FROM V$DATABASE;

SUPPLEME SUP SUP
-------- --- ---
NO NO NO

SQL> SELECT MEMBER FROM V$LOGFILE WHERE GROUP#=(SELECT GROUP# FROM V$LOG WHERE S
TATUS='CURRNT');

未选定行

SQL> SELECT MEMBER FROM V$LOGFILE WHERE GROUP#=(SELECT GROUP# FROM V$LOG WHERE S
TATUS='CURRENT');

MEMBER
------------------------------------------------------------
C:ORACLEPRODUCT10.2.0ORADATATOMSYANREDO01.RDO

SQL> CREATE TABLE TEST(ID INT,NAME VARCHAR2(20));

表已创建。

SQL> INSERT INTO TEST VALUES(1,'YAN');

已创建 1 行。

SQL> COMMIT;

提交完成。

SQL> ALTER SYSTEM SWITCH LOGFILE;

系统已更改。

SQL> EXEC SYS.DBMS_LOGMNR.ADD_LOGFILE(logfilename=>'C:ORACLEPRODUCT10.2.0ORA
DATATOMSYANREDO01.RDO',options=>SYS.DBMS_LOGMNR.NEW);

PL/SQL 过程已成功完成。

SQL> SELECT FILENAME FROM V$LOGMNR_LOGS;

FILENAME
--------------------------------------------------------------------------------

C:ORACLEPRODUCT10.2.0ORADATATOMSYANREDO01.RDO

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='ADMIN' AND TABLE_NA
ME='TEST';

SQL_REDO
--------------------------------------------------------------------------------

CREATE TABLE TEST(ID INT,NAME VARCHAR2(20));
insert into "ADMIN"."TEST"("ID","NAME") values ('1','YAN');

SQL> EXEC SYS.DBMS_LOGMNR.END_LOGMNR;

PL/SQL 过程已成功完成。

我在LINUX平台数据库版本10.2.0.3.0下 又做了一次测试。也没问题。以前的时候我也遇到过捕获不到的问题。怎么这次就OK了。有点困惑。下面是我在LINUX下的测试过程。本来想用10.2.0.1.0来测试的,由于临时没有LINUX10.2.0.1版本的数据库,只能用10.2.0.3.0先代替了。

C:>sqlplus admin/admin@racdb

SQL*Plus: Release 10.2.0.1.0 - Production on 星期四 1月 14 10:45:24 2010

Copyright (c) 1982, 2005, Oracle. All rights reserved.

连接到:
Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 - Production
With the Partitioning, Real Application Clusters, OLAP and Data Mining options

SQL> SELECT FORCE_LOGGING,SUPPLEMENTAL_LOG_DATA_MIN,SUPPLEMENTAL_LOG_DATA_PK,SUP
PLEMENTAL_LOG_DATA_UI FROM V$DATABASE;

FORCE_ SUPPLEMENTAL_LOG SUPPLE SUPPLE
------ ---------------- ------ ------
NO NO NO NO

SQL> SELECT INSTANCE_NAME,THREAD# FROM V$INSTANCE;

INSTANCE_NAME THREAD#
-------------------------------- ----------
racdb1 1

SQL> SELECT MEMBER FROM V$LOGFILE WHERE GROUP#=(SELECT GROUP# FROM V$LOG WHERE T
HREAD#=1 AND STATUS='CURRENT');

MEMBER
--------------------------------------------------------------------------------

+DGDATA/racdb/onlinelog/group_2.268.706201479
+RECOVERYDEST/racdb/onlinelog/group_2.261.706201479

SQL> CREATE TABLE TEST(ID INT,NAME VARCHAR2(20));
CREATE TABLE TEST(ID INT,NAME VARCHAR2(20))
*
第 1 行出现错误:
ORA-00955: 名称已由现有对象使用

SQL> CREATE TABLE T(ID INT,NAME VARCHAR2(20));

表已创建。

SQL> INSERT INTO T VALUES(1,'YAN');

已创建 1 行。

SQL> COMMIT;

提交完成。

SQL> ALTER SYSTEM SWITCH LOGFILE;

系统已更改。

SQL> EXEC SYS.DBMS_LOGMNR.ADD_LOGFILE(logfilename=>'+DGDATA/racdb/onlinelog/grou
p_2.268.706201479',options=>SYS.DBMS_LOGMNR.NEW);

PL/SQL 过程已成功完成。

SQL> SELECT FILENAME FROM V$LOGMNR_LOGS;

FILENAME
--------------------------------------------------------------------------------

+DGDATA/racdb/onlinelog/group_2.268.706201479

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='ADMIN' AND TABLE_NA
ME='T';

SQL_REDO
--------------------------------------------------------------------------------

CREATE TABLE T(ID INT,NAME VARCHAR2(20));
insert into "ADMIN"."T"("ID","NAME") values ('1','YAN');

SQL> EXEC SYS.DBMS_LOGMNR.END_LOGMNR;

PL/SQL 过程已成功完成。

SQL> SELECT * FROM V$VERSION;

BANNER
-----------------------------------------------------

Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 - Prod
PL/SQL Release 10.2.0.3.0 - Production
CORE 10.2.0.3.0 Production
TNS for Linux: Version 10.2.0.3.0 - Production
NLSRTL Version 10.2.0.3.0 - Production

寒 评论于: 2010.01.14 11:10
re: Oracle10G LOGMNR捕获不到记录(一) [回复]

我没有说一定捕获不到,你如果多尝试几次,就会碰到捕获不到的情况。因此,期望通过默认设置的LOGMNR获取修改数据是不可靠的。

yangtingkun 评论于: 2010.01.15 13:43
re: Oracle10G LOGMNR捕获不到记录(一) [回复]

原来如此。这个捕获不到的问题我老早也遇到过。当初我还以为我的数据库环境问题。突看来如果要想可靠只能加补充日志了。smile

寒 评论于: 2010.01.15 16:53

发表评论
标题

在此添加评论
表情符号: smile laughing tongue angry crying sad wassat wink

称呼

邮箱地址(可选)

个人主页(可选)

 authimage


切换风格
新闻聚合
博客日历
文章归档...
最新发表...
最新评论...
最多阅读文章...
最多评论文章...
博客统计...
Blog信息
网站链接...