Oracle 11.2.0.3 重做日志的问题

Trouble with Oracle 11.2.0.3 redo logs

我在 oracle 11.2.0.3 中有一个 table,我想在重做日志中捕获它。问题是它有一个 sdo_geometry 字段。这是我无法更改的遗产 table。但好消息是我不需要 sdo_geometry 字段。 所以我创建了一个物化视图,如下所示。

CREATE MATERIALIZED VIEW LOG ON LEGACY_TABLE_NAME
WITH PRIMARY KEY
INCLUDING NEW VALUES;
CREATE MATERIALIZED VIEW LEGACY_TABLE_NAME_MV
  NOLOGGING
  NOCACHE
  BUILD IMMEDIATE 
  REFRESH FAST ON COMMIT 
  WITH PRIMARY KEY
  AS
    SELECT <List of non sdo_gemoetry columns> FROM LEGACY_TABLE_NAME;

当我进行更新并查看重做日志时,问题出现了。我没有看到更新语句,而是看到了删除和插入语句。由于我使用的是主键,因此我希望看到更新语句。

有谁知道我需要做什么才能确保在重做日志中看到更新语句。

谢谢

我认为您误解了 redolog 存储的内容和 materiliazed view log 的存储内容。

让我们尝试对这两种情况进行测试:

  • LogMiner 验证重做日志文件的内容,我们可以使用 v$LOGMNR_CONTENTS.
  • 查看
  • 实体化视图日志和更新操作示例

甲骨文版本:12.2

重做日志内容

SQL> create table cpl_rep.test_redo_logs ( c1 number primary key , c2 number ) ;

Table created.

SQL> insert into cpl_rep.test_redo_logs values ( 1 , 1 );

1 row created.

SQL> insert into cpl_rep.test_redo_logs values ( 2 , 2 );

1 row created.

SQL> commit ;

Commit complete.

SQL> update cpl_rep.test_redo_logs set c1=3 , c2=3 where c1 = 2 ;

1 row updated.

SQL> commit ;

Commit complete.

SQL> select * from cpl_rep.test_redo_logs ;

        C1         C2
---------- ----------
         1          1
         3          3

SQL> exit
Disconnected from Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit 
Production
$ sqlplus / as sysdba

SQL*Plus: Release 12.2.0.1.0 Production on Sat Aug 8 21:53:05 2020

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


Connected to:
Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production

SQL> alter system switch logfile ;

System altered.

SQL> exit
Disconnected from Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit 
Production

现在让我们通过将重做日志文件加载到 LogMiner 来启动 LogMiner 会话:

SQL> exec dbms_logmnr.add_logfile('/bbdd_odcgrc1r/redo1/redo11.ora' , 1);
SQL> exec dbms_logmnr.add_logfile('/bbdd_odcgrc1r/redo2/redo21.ora' , 1);
SQL> exec dbms_logmnr.add_logfile('/bbdd_odcgrc1r/redo1/redo12.ora' , 1);
SQL> exec dbms_logmnr.add_logfile('/bbdd_odcgrc1r/redo2/redo22.ora' , 1);
SQL> exec dbms_logmnr.add_logfile('/bbdd_odcgrc1r/redo1/redo13.ora' , 1);
SQL> exec dbms_logmnr.add_logfile('/bbdd_odcgrc1r/redo2/redo23.ora' , 1);

PL/SQL procedure successfully completed.

PL/SQL procedure successfully completed.

PL/SQL procedure successfully completed.

PL/SQL procedure successfully completed.

PL/SQL procedure successfully completed.

PL/SQL procedure successfully completed.

SQL> exec dbms_logmnr.start_logmnr(options=>dbms_logmnr.dict_from_online_catalog);

PL/SQL procedure successfully completed.

SQL> select count(*) from v$logmnr_contents where seg_name = upper('test_redo_logs') ;

COUNT(*)
----------
         4

SQL> select sql_redo , seg_name from v$logmnr_contents where seg_name = upper('test_redo_logs') ;

SQL_REDO
--------------------------------------------------------------------------------
SEG_NAME
--------------------------------------------------------------------------------
create table cpl_rep.test_redo_logs ( c1 number primary key , c2 number ) ;
TEST_REDO_LOGS

insert into "CPL_REP"."TEST_REDO_LOGS"("C1","C2") values ('1','1');
TEST_REDO_LOGS

insert into "CPL_REP"."TEST_REDO_LOGS"("C1","C2") values ('2','2');
TEST_REDO_LOGS


SQL_REDO
--------------------------------------------------------------------------------
SEG_NAME
--------------------------------------------------------------------------------
update "CPL_REP"."TEST_REDO_LOGS" set "C1" = '3', "C2" = '3' where "C1" = '2' an
d "C2" = '2' and ROWID = 'AAGKh2AAAAAJIH1AAB';
TEST_REDO_LOGS

正如您在上面看到的,UPDATEV$LOGMNR_CONTENTSSQL_REDO 列中的任何其他 DML 操作一样正常显示。所以,很明显,只要操作是在日志模式下完成的,或者数据库是在强制日志模式下,重做文件就会存储任何更新操作,在这种情况下,操作是什么模式并不重要,因为它总是存储。

物化视图日志

让我们像您在问题中所做的那样创建一个 materialized view log 和一个 materialized view。但是,为了验证 MLOG$ tables 的内容,我将按需刷新,而不是在提交时刷新。

SQL> create table x ( c1 number primary key , c2 number ) ;

Table created.

SQL> insert into x values ( 1 , 1 ) ;

1 row created.

SQL> insert into x values ( 2 , 2 );

1 row created.

SQL> commit ;

Commit complete.

SQL> create materialized view log on x with primary key including new values ;

Materialized view log created.

SQL> create materialized view mv_x nologging nocache build immediate refresh fast on demand with primary key as select c1 , c2 from x ;

Materialized view created.

SQL> select * from x ;

        C1         C2
---------- ----------
         1          1
         2          2

SQL> select * from mv_x ;

        C1         C2
---------- ----------
         1          1
         2          2

SQL> insert into x values ( 3 , 3 );

1 row created.

SQL> commit ;

Commit complete.

SQL> update x set c1=4 , c2=4 where c1=3 ;

1 row updated.

SQL> commit ;

Commit complete.

由于我们确实创建了按需刷新的物化视图,现在让我们来看看 MLOG$ table

的内容
SQL>  select * from x ;

        C1         C2
---------- ----------
         1          1
         2          2
         4          4

SQL> select * from mv_x ;

        C1         C2
---------- ----------
         1          1
         2          2

SQL> select * from mlog$_x

        C1 SNAPTIME$ D O CHANGE_VEC                        XID$$
---------- --------- - - ---------- ----------------------------
         3 01-JAN-00 I N FE                    39406677128122001
         3 01-JAN-00 D O 00                    44473269658586765
         4 01-JAN-00 I N FF                    44473269658586765

那我刷新

SQL>  select * from x ;

        C1         C2
---------- ----------
         1          1
         2          2
         4          4

SQL> select * from mv_x ;

        C1         C2
---------- ----------
         1          1
         2          2

SQL> exec dbms_mview.refresh('MV_X') ;

PL/SQL procedure successfully completed.

SQL> select * from mv_x ;

        C1         C2
---------- ----------
         1          1
         2          2
         4          4

SQL> select * from mlog$_x
  2  ;

no rows selected

您在 DMLTYPE$$ 上看不到 UPDATE 的原因是您在实体化视图创建中选择主键作为 WITH 子句。在这种情况下,只有 D 或 I 会出现在列 DMLTYPE$$ 中,但是当它是更新时,你会得到两行具有相同事务 ID(上例中的 XID$$ 字段具有相同的价值)

但是,请检查当我使用 ROWID 而不是 PRIMARY KEY

时会发生什么
SQL> create materialized view log on x with rowid including new values ;

Materialized view log created.

SQL> create materialized view mv_x nologging nocache build immediate refresh fast on demand with rowid as select c1 , c2 from cpl_rep.x ;

Materialized view created.

SQL> select * from cpl_rep.mv_x ;

        C1         C2
---------- ----------
         1          1
         2          2
         3          3

SQL> select * from x ;

        C1         C2
---------- ----------
         1          1
         2          2
         3          3

SQL> insert into x values ( 4 , 4 ) ;

1 row created.

SQL> commit ;

Commit complete.

SQL> insert into x values ( 5 , 5 );

1 row created.

SQL> commit ;

Commit complete.

SQL> update x set c1=6 , c2=6 where c1=5 ;

1 row updated.

SQL> commit ;

Commit complete.

SQL> select * from x ;

        C1         C2
---------- ----------
         1          1
         2          2
         3          3
         4          4
         6          6

SQL> select * from mv_x ;

        C1         C2
---------- ----------
         1          1
         2          2
         3          3

现在来看看M$LOGtable的内容

SQL> col m_row$$ for a18
SQL> select * from mlog$_x ;

M_ROW$$            SNAPTIME$ D O CHANGE_VEC                        XID$$
------------------ --------- - - ---------- ----------------------------
AAGKh/AAAAAJJWnAAD 01-JAN-00 I N FE                     3659458165104006
AAGKh/AAAAAJJWnAAE 01-JAN-00 I N FE                    44754731750395757
AAGKh/AAAAAJJWnAAE 01-JAN-00 U U 06                    12948119511653544
AAGKh/AAAAAJJWnAAE 01-JAN-00 U N 06                    12948119511653544

我现在有 4 行,2 行用于插入,1 行用于字段 C1,另一行用于字段 C2,它们实际上是同一事务(字段 XID$$

我希望它能阐明当您选择 ROWID 或 PRIMARY KEYY 时如何填充 MLOG$ table。请注意,使用主键的物化视图日志 tables 也有 rupd$_ tables。 rupd$_ table 支持可更新的物化视图,这只能在具有主键的日志 tables 上实现。