logmnr使用

SQL> @?/rdbms/admin/dbmslm.sql
程序包已创建。
授权成功。
SQL> @?/rdbms/admin/dbmslmd.sql
程序包已创建。
SQL> @?/rdbms/admin/dbmslms.sql
程序包已创建。
没有错误。
授权成功。

SQL> show parameter utl

NAME                                 TYPE        VALUE
------------------------------------ ----------- -------------------
create_stored_outlines               string
utl_file_dir                         string
SQL> alter system set utl_file_dir='G:\logmnr' scope=spfile;
系统已更改。
SQL> startup force
ORACLE 例程已经启动。
Total System Global Area 1258291200 bytes
Fixed Size                  1250548 bytes
Variable Size             360712972 bytes
Database Buffers          889192448 bytes
Redo Buffers                7135232 bytes
数据库装载完毕。
数据库已经打开。
SQL> exec dbms_logmnr_d.build('dictionary.ora','G:\logmnr');
PL/SQL 过程已成功完成。
SQL> create table lgmnr_test(a number,b number,c number,d number)

表已创建。
SQL> insert into lgmnr_test values(1,2,3,4);
已创建 1 行。
SQL> insert into lgmnr_test values(2,3,4,5);
已创建 1 行。
SQL> insert into lgmnr_test values(3,4,5,6);
已创建 1 行。
SQL> insert into lgmnr_test values(4,5,6,7);
已创建 1 行。
SQL> commit;
提交完成。

一logmnr的数据字典选项的测试
这个测试是使用的在线字典的方式,所以没有build
首先,我们必须打开最小追加日志模式,才能运用logmnr查询到DML操作的日志信息。 


SQL> update lgmnr_test set c=9 where b=3;
已更新 1 行。
SQL> commit;
提交完成。
SQL> select * from v$log;


    GROUP#    THREAD#  SEQUENCE#      BYTES    MEMBERS ARC STATUS
---------- ---------- ---------- ---------- ---------- --- ----------
FIRST_CHANGE# FIRST_TIME
------------- --------------
         1          1         22   52428800          1 YES INACTIVE
       760601 11-4月 -14


         2          1         23   52428800          1 YES INACTIVE
       760603 11-4月 -14


         3          1         24   52428800          1 NO  CURRENT
       760606 11-4月 -14

SQL> alter system switch logfile;

系统已更改。
SQL> exec DBMS_LOGMNR.ADD_LOGFILE (LOGFILENAME => 'D:\oracle\product\10.2.0\oradata\ocm\redo03.log',options=>dbms_logmnr.new);

PL/SQL 过程已成功完成。

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

PL/SQL 过程已成功完成。

SQL> create table content as select * from v$logmnr_contents;
表已创建。

SELECT * FROM CONTENT WHERE seg_name LIKE 'LGMNR%';没有记录
这里面没有记录的原因是没有启用最小追加模式
SQL> select supplemental_log_data_min from v$database;
SUPPLEME
--------
NO

启用追加模式
alter database add supplemental log data;
SQL> create table baixyu(id1 int,id2 int,id3 int);
表已创建。
SQL> insert into baixyu values(1,2,3);
已创建 1 行。
SQL> insert into baixyu values(2,3,4);
已创建 1 行。
SQL> insert into baixyu values(3,4,5);
已创建 1 行。
SQL> commit;
提交完成。
SQL> update baixyu set id1=66 where id1=2;
已更新 1 行。
SQL> commit;
提交完成。
SQL> select * from v$log;
    GROUP#    THREAD#  SEQUENCE#      BYTES    MEMBERS ARC STATUS
---------- ---------- ---------- ---------- ---------- --- ----------------
FIRST_CHANGE# FIRST_TIME
------------- --------------
         1          1         25   52428800          1 NO  CURRENT
       760926 11-4月 -14


         2          1         23   52428800          1 YES INACTIVE
       760603 11-4月 -14


         3          1         24   52428800          1 YES INACTIVE
       760606 11-4月 -14

SQL> alter system switch logfile;
系统已更改。
SQL>  exec DBMS_LOGMNR.ADD_LOGFILE (LOGFILENAME => 'D:\oracle\product\10.2.0\oradata\ocm\redo01.log',options=>dbms_logmnr.new);
PL/SQL 过程已成功完成。
SQL> exec dbms_logmnr.start_logmnr(options=>dbms_logmnr.dict_from_online_catalog);
PL/SQL 过程已成功完成。
SQL> create table bak as select * from v$logmnr_contents;
表已创建。
SQL> SELECT ROWID,operation,sql_redo,sql_undo FROM bak WHERE seg_name LIKE 'BAIX%';


ROWID            OPERATION  SQL_REDO                                                               SQL_UNDO
---------------- ---------- ---------------------------------------------------------------------- ------------------------------------------
--------
AAAMkYAABAAAPfeA DDL        create table baixyu(id1 int,id2 int,id3 int);
AE


AAAMkYAABAAAPffA INSERT     insert into "SYS"."BAIXYU"("ID1","ID2","ID3") values ('1','2','3');    delete from "SYS"."BAIXYU" where "ID1" = '
1' and "
AD                                                                                                 ID2" = '2' and "ID3" = '3' and ROWID = 'AA
AMkXAABA
                                                                                                   AAPVqAAA';


AAAMkYAABAAAPgXA INSERT     insert into "SYS"."BAIXYU"("ID1","ID2","ID3") values ('2','3','4');    delete from "SYS"."BAIXYU" where "ID1" = '
2' and "
AH                                                                                                 ID2" = '3' and "ID3" = '4' and ROWID = 'AA
AMkXAABA
                                                                                                   AAPVqAAB';




ROWID            OPERATION  SQL_REDO                                                               SQL_UNDO
---------------- ---------- ---------------------------------------------------------------------- ------------------------------------------
--------
AAAMkYAABAAAPgXA INSERT     insert into "SYS"."BAIXYU"("ID1","ID2","ID3") values ('3','4','5');    delete from "SYS"."BAIXYU" where "ID1" = '
3' and "
AI                                                                                                 ID2" = '4' and "ID3" = '5' and ROWID = 'AA
AMkXAABA
                                                                                                   AAPVqAAC';


AAAMkYAABAAAPgYA UPDATE     update "SYS"."BAIXYU" set "ID1" = '66' where "ID1" = '2' and ROWID = ' update "SYS"."BAIXYU" set "ID1" = '2' wher
e "ID1"
AA                          AAAMkXAABAAAPVqAAB';                                                   = '66' and ROWID = 'AAAMkXAABAAAPVqAAB';






抽取字典信息到在线日志中
这种方法必须处于归档模式下
SQL> select * from baixyu;


       ID1        ID2        ID3
---------- ---------- ----------
         1          2          3
        66          3          4
         3          4          5

SQL> update baixyu set id2=90 where id2=3;
已更新 1 行。
SQL> select group#,sequence#,archived,status from v$log;
    GROUP#  SEQUENCE# ARC STATUS
---------- ---------- --- ----------------
         1         25 YES INACTIVE
         2         26 NO  CURRENT
         3         24 YES INACTIVE
SQL> alter system switch logfile;
系统已更改。
SQL> col name for a40
SQL> select name from v$archived_log where sequence#=26;
NAME
----------------------------------------
D:\ORACLE\PRODUCT\10.2.0\FLASH_RECOVERY_AREA\OCM\ARCHIVELOG\2014_04_11\O1_MF_1_26_9NGPO3G4_.ARC

SQL> exec dbms_logmnr_d.build(options=>dbms_logmnr_d.store_in_redo_logs);
PL/SQL 过程已成功完成。
SQL> select sequence#,name from v$archived_log where dictionary_begin='YES';
 SEQUENCE# NAME
---------- ----------------------------------------
        28 D:\ORACLE\PRODUCT\10.2.0\FLASH_RECOVERY_AREA\OCM\ARCHIVELOG\2014_04_11\O1_MF_1_28_9NGPSCXN_.ARC

看到build的数据字典保存到了28序列中去了
SQL> exec dbms_logmnr.add_logfile('D:\ORACLE\PRODUCT\10.2.0\FLASH_RECOVERY_AREA\OCM\ARCHIVELOG\2014_04_11\O1_MF_1_28_9NGPSCXN_.ARC',dbms_logm
nr.new);

PL/SQL 过程已成功完成。
SQL> exec dbms_logmnr.add_logfile('D:\ORACLE\PRODUCT\10.2.0\FLASH_RECOVERY_AREA\OCM\ARCHIVELOG\2014_04_11\O1_MF_1_26_9NGPO3G4_.ARC',dbms_logm
nr.addfile);

PL/SQL 过程已成功完成。
SQL> exec dbms_logmnr.start_logmnr(options=>dbms_logmnr.dict_from_redo_logs+dbms_logmnr.print_pretty_sql);
PL/SQL 过程已成功完成。
SQL> create table bak2 as select * from v$logmnr_contents;
SQL> SELECT ROWID,operation,sql_redo,sql_undo FROM bak2 WHERE seg_name LIKE 'BAIX%';


ROWID            OPERATION  SQL_REDO                                                               SQL_UNDO
---------------- ---------- ---------------------------------------------------------------------- -------------------------------------
--------
AAAMmZAABAAAP23A UPDATE     update "SYS"."BAIXYU"                                                  update "SYS"."BAIXYU"
AD                            set                                                                    set
                                "ID2" = 90                                                             "ID2" = 3
                              where                                                                  where
                                "ID2" = 3 and                                                          "ID2" = 90 and
                                ROWID = 'AAAMkXAABAAAPVqAAB';                                          ROWID = 'AAAMkXAABAAAPVqAAB';


3外部字典方式
SQL> select * from lgmnr_test;

         A          B          C          D
---------- ---------- ---------- ----------
         1          2          3          4
         2          3          9          5
         3          4          5          6
         4          5          6          7

SQL> show parameter utl
NAME                                 TYPE        VALUE
------------------------------------ ----------- ---------------------
create_stored_outlines               string
utl_file_dir                         string      G:\logmnr

SQL> update lgmnr_test set a=99 where c=5;
已更新 1 行。
SQL> commit;
提交完成。
SQL> select group#,sequence#,archived,status from v$log;
    GROUP#  SEQUENCE# ARC STATUS
---------- ---------- --- ----------------
         1         34 NO  CURRENT
         2         32 YES INACTIVE
         3         33 YES ACTIVE
alter system switch logfile;
SQL> exec dbms_logmnr_d.build('dictionary.ora','G:\logmnr',dbms_logmnr_d.store_in_flat_file);
PL/SQL 过程已成功完成。
SQL> exec sys.dbms_logmnr.add_logfile('D:\oracle\product\10.2.0\oradata\ocm\redo02.log',dbms_logmnr.new);
PL/SQL 过程已成功完成。
SQL> exec dbms_logmnr.start_logmnr(dictfilename=>'G:\logmnr\dictionary.ora',options=>dbms_logmnr.print_pretty_sql);
PL/SQL 过程已成功完成。

create table bak5 as select * from v$logmnr_contents;
SQL> SELECT ROWID,operation,sql_redo,sql_undo FROM bak5 WHERE seg_name LIKE 'LG%';


ROWID            OPERATION  SQL_REDO                                                               SQL_UNDO
---------------- ---------- ---------------------------------------------------------------------- ----------------------------------------
--------
AAAMmgAABAAAXRyA UPDATE     update "SYS"."LGMNR_TEST"                                              update "SYS"."LGMNR_TEST"
AF                            set                                                                    set
                                "A" = 99                                                               "A" = 3
                              where                                                                  where
                                "A" = 3 and                                                            "A" = 99 and
                                ROWID = 'AAAMkKAABAAAPOiAAC';                                          ROWID = 'AAAMkKAABAAAPOiAAC';


表结构发生改变情况下的测试

SQL> select * from lgmnr_test;
         A          B          C          D
---------- ---------- ---------- ----------
         1          2          3          4
         2          3          9          5
        99          4          5          6
        99          5          6          7


SQL> update lgmnr_test set a=100 where c=3;
已更新 1 行。
SQL> commit;
提交完成。
SQL> select group#,sequence#,status from v$log;
    GROUP#  SEQUENCE# STATUS
---------- ---------- ----------------
         1         52 CURRENT
         2         50 INACTIVE
         3         51 INACTIVE
SQL> alter system switch logfile;
系统已更改。
SQL> select name from v$archived_log where sequence#=52;
NAME
----------------------------------------
D:\ORACLE\PRODUCT\10.2.0\FLASH_RECOVERY_AREA\OCM\ARCHIVELOG\2014_04_11\O1_MF_1_52_9NGSQSS4_.ARC
SQL> drop table lgmnr_test;
表已删除。
SQL> exec dbms_logmnr.add_logfile('D:\ORACLE\PRODUCT\10.2.0\FLASH_RECOVERY_AREA\OCM\ARCHIVELOG\2014_04_11\O1_MF_1_52_9NGSQSS4_.ARC',dbms_log
nr.new);
PL/SQL 过程已成功完成。
SQL> exec dbms_logmnr.start_logmnr(options=>dbms_logmnr.dict_from_online_catalog+dbms_logmnr.print_pretty_sql);
PL/SQL 过程已成功完成。
SQL> create table bak7 as select * from v$logmnr_contents;
表已创建。

**********************************************查看没有数据,下面的是换一个用户实验的,不是在sys下面

SQL> create table abs(id1 int,id2 int);
表已创建。
SQL> insert into abs values(1,2);
已创建 1 行。
SQL> insert into abs values(2,3);
已创建 1 行。
commit
提交完成
SQL> update abs set id1=999;
已更新2行。
commit
提交完成。
SQL> select * from v$log;
   GROUP#    THREAD#  SEQUENCE#      BYTES    MEMBERS ARC STATUS           FIRST_CHANGE# FIRST_TIME
--------- ---------- ---------- ---------- ---------- --- ---------------- ------------- -----------
        1          1         58   52428800          1 NO  CURRENT                 783219 11-4月 -14
        2          1         56   52428800          1 YES INACTIVE                780784 11-4月 -14
        3          1         57   52428800          1 YES INACTIVE                781167 11-4月 -14

SQL> alter system switch logfile;
系统已更改。
SQL> select name from v$archived_log where sequence#=58;
NAME
--------------------------------------------------------------------------------
D:\ORACLE\PRODUCT\10.2.0\FLASH_RECOVERY_AREA\OCM\ARCHIVELOG\2014_04_11\O1_MF_1_58_9NH0RGLT_.ARC

SQL> exec sys.dbms_logmnr.add_logfile('D:\ORACLE\PRODUCT\10.2.0\FLASH_RECOVERY_AREA\OCM\ARCHIVELOG\2014_04_11\O1_MF_1_58_9NH0RGLT_.ARC',sys.dbms_logmnr.new);
PL/SQL 过程已成功完成。
SQL> exec sys.dbms_logmnr.start_logmnr(options=>sys.dbms_logmnr.dict_from_online_catalog+sys.dbms_logmnr.print_pretty_sql);

反正这个就要使用DICT_FROM_REDO_LOGS

三使用scn来指定分析的范围,并且自动添加日志
SQL> select dbms_flashback.get_system_change_number from dual;
GET_SYSTEM_CHANGE_NUMBER
------------------------
                  784308
SQL> update logmnr_test set a=100;
已更新3行。
SQL> commit;
提交完成。
SQL> select dbms_flashback.get_system_change_number from dual;
GET_SYSTEM_CHANGE_NUMBER
------------------------
                  784316
exec dbms_logmnr.start_logmnr(startscn=>784308,endscn=>784316,options=>dbms_logmnr.dict_from_online_catalog+dbms_logmnr.continuous_mine+dbms_logmnr.print_pretty_sql);
当我们在源数据库上使用logmnr来分析日志时,我们可以不添加日志,而是使用CONTINUOUS_MINE来让LOGMNR自动搜索控制文件,通过指定SCN或者TIME的范围,来找出对应的日志文件自动添加
SQL> SELECT timestamp,operation,sql_redo,sql_undo FROM bak99 WHERE seg_name='LOGMNR_TEST';
TIMESTAMP      OPERA SQL_REDO                                           SQL_UNDO
-------------- ----- -------------------------------------------------- -------------------------------------------------
11-4月 -14     UPDAT update "SYS"."LOGMNR_TEST"                         update "SYS"."LOGMNR_TEST"
               E       set                                                set
                         "A" = 100                                          "A" = 1
                       where                                              where
                         "A" = 1 and                                        "A" = 100 and
                         ROWID = 'AAAMmrAABAAAbDyAAA';                      ROWID = 'AAAMmrAABAAAbDyAAA';


11-4月 -14     UPDAT update "SYS"."LOGMNR_TEST"                         update "SYS"."LOGMNR_TEST"
               E       set                                                set
                         "A" = 100                                          "A" = 2
                       where                                              where


TIMESTAMP      OPERA SQL_REDO                                           SQL_UNDO
-------------- ----- -------------------------------------------------- -------------------------------------------------
                         "A" = 2 and                                        "A" = 100 and
                         ROWID = 'AAAMmrAABAAAbDyAAB';                      ROWID = 'AAAMmrAABAAAbDyAAB';


11-4月 -14     UPDAT update "SYS"."LOGMNR_TEST"                         update "SYS"."LOGMNR_TEST"
               E       set                                                set
                         "A" = 100                                          "A" = 3
                       where                                              where
                         "A" = 3 and                                        "A" = 100 and
                         ROWID = 'AAAMmrAABAAAbDyAAC';                      ROWID = 'AAAMmrAABAAAbDyAAC';


no_rowid_in_stmt测试

ROWID在两个逻辑数据库上应用是不一致的 
干脆就把ROWID去掉 
否则还影响SQL的可用性 
在上面的测试中我们看到在每一个sql_redo的后面都是有一个rowid

SQL> delete logmnr_test where a=100;
已删除3行。
SQL> commit;
提交完成。
SQL> select * from v$log;
    GROUP#    THREAD#  SEQUENCE#      BYTES    MEMBERS ARC STATUS           FIRST_CHANGE# FIRST_TIME
---------- ---------- ---------- ---------- ---------- --- ---------------- ------------- --------------
         1          1         58   52428800          1 YES INACTIVE                783219 11-4月 -14
         2          1         59   52428800          1 YES INACTIVE                783757 11-4月 -14
         3          1         60   52428800          1 NO  CURRENT                 784044 11-4月 -14
alter system switch logfile;
exec sys.dbms_logmnr.add_logfile('D:\oracle\product\10.2.0\oradata\ocm\redo01.log',sys.dbms_logmnr.new);
PL/SQL 过程已成功完成。
SQL> exec sys.dbms_logmnr.start_logmnr(options=>sys.dbms_logmnr.dict_from_online_catalog+dbms_logmnr.no_rowid_in_stmt+sys.dbms_logmnr.print_pretty_sql);
SELECT timestamp,operation,sql_redo,sql_undo FROM bak88 WHERE seg_name='LOGMNR_TEST';
SQL> SELECT timestamp,operation,sql_redo,sql_undo FROM bak88 WHERE seg_name='LOGMNR_TEST';
TIMESTAMP      OPERA SQL_REDO                                           SQL_UNDO
-------------- ----- -------------------------------------------------- --------------------------------
11-4月 -14     INSER insert into "SYS"."LOGMNR_TEST"                    delete from "SYS"."LOGMNR_TEST"
               T      values                                             where
                         "A" = 4,                                           "A" = 4 and
                         "B" = 5;                                           "B" = 5;


11-4月 -14     UPDAT update "SYS"."LOGMNR_TEST"                         update "SYS"."LOGMNR_TEST"
               E       set                                                set
                         "A" = 45                                           "A" = 4
                       where                                              where
                         "A" = 4;                                           "A" = 45;

看到是没有rowid了的。

实验committed_data_only的测试
在日志中有已提交的和未提交的redo,如何让logmnr只生成已提交的redo
SQL> insert into logmnr_test values(111,222);
已创建 1 行。
SQL> commit;
提交完成。
SQL> select * from logmnr_test;
         A          B
---------- ----------
       111        222
        45          5
SQL> update logmnr_test set a=789 where b=5;
已更新 1 行。
SQL> select * from v$log;
    GROUP#    THREAD#  SEQUENCE#      BYTES    MEMBERS ARC STATUS           FIRST_CHANGE# FIRST_TIME
---------- ---------- ---------- ---------- ---------- --- ---------------- ------------- --------------
         1          1         67   52428800          1 YES INACTIVE                785583 11-4月 -14
         2          1         68   52428800          1 NO  CURRENT                 785647 11-4月 -14
         3          1         66   52428800          1 YES INACTIVE                785501 11-4月 -14
alter system switch logfile;
SQL> commit;
提交完成。
exec dbms_logmnr.add_logfile('D:\oracle\product\10.2.0\oradata\ocm\redo02.log',dbms_logmnr.new);
exec dbms_logmnr.start_logmnr(options=>dbms_logmnr.dict_from_online_catalog+dbms_logmnr.committed_data_only+dbms_logmnr.print_pretty_sql);
SQL> SELECT timestamp,operation,sql_redo,sql_undo FROM bak987 WHERE seg_name='LOGMNR_TEST';
TIMESTAMP      OPERA SQL_REDO                                           SQL_UNDO
-------------- ----- -------------------------------------------------- ----------------------------------------
11-4月 -14     INSER insert into "SYS"."LOGMNR_TEST"                    delete from "SYS"."LOGMNR_TEST"
               T      values                                             where
                         "A" = 111,                                         "A" = 111 and
                         "B" = 222;                                         "B" = 222 and
                                                                            ROWID = 'AAAMmrAABAAAbDyAAA';


看到记录中只有1条,第二个未提交的没有看到。

最小追加日志模式的测试

打开最小追加模式
alter database add supplemental log data;
删除最小追加模式
alter database drop supplemental log data;

隐士打开最小追加日志的测试supplemental_log_data_min=implicit测试
1删除最小追加模式
alter database drop supplemental log data;
2在数据库级打开主键追加日志
alter database add supplemental log data(primary key) columns;

SQL> select supplemental_log_data_min min,supplemental_log_data_pk pk,supplemental_log_data_ui ui,supplemental_log_data_fk fk,supplemental_log_data_all from v$database;
MIN      PK  UI  FK  SUP
-------- --- --- --- ---
IMPLICIT YES NO  NO  NO

SQL> update logmnr_test set a=999 where b=5;
已更新 1 行。
SQL> commit;
提交完成。
SQL> select * from v$log;
    GROUP#    THREAD#  SEQUENCE#      BYTES    MEMBERS ARC STATUS
---------- ---------- ---------- ---------- ---------- --- -------------
FIRST_CHANGE# FIRST_TIME
------------- --------------
         1          1         67   52428800          1 YES INACTIVE
       785583 11-4月 -14


         2          1         68   52428800          1 YES INACTIVE
       785647 11-4月 -14


         3          1         69   52428800          1 NO  CURRENT
       787176 11-4月 -14

  exec dbms_logmnr.add_logfile('D:\oracle\product\10.2.0\oradata\ocm\redo03.log',dbms_logmnr.new);
  exec dbms_logmnr.start_logmnr(options=>dbms_logmnr.dict_from_online_catalog+dbms_logmnr.print_pretty_sql);
SQL> SELECT timestamp,operation,sql_redo,sql_undo FROM bak456 WHERE seg_name='LOGMNR_TEST';
TIMESTAMP      OPERA SQL_REDO                                           SQL_UNDO
-------------- ----- -------------------------------------------------- ------------------------------------------
11-4月 -14     UPDAT update "SYS"."LOGMNR_TEST"                         update "SYS"."LOGMNR_TEST"
               E       set                                                set
                         "A" = 999                                          "A" = 789
                       where                                              where
                         "A" = 789 and                                      "A" = 999 and
                         "B" = 5 and                                        "B" = 5 and
                         ROWID = 'AAAMmrAABAAAbDyAAD';                      ROWID = 'AAAMmrAABAAAbDyAAD';


看到在pk下面where中,所有列的值有存在了。是因为这个表中没有定义pk,所以把全部的列都显示出来了,作为一个pk

七设置数据库级primary key追加日志
SQL> alter database add supplemental log data(primary key)columns;
数据库已更改。
SQL> alter table logmnr_test add constraint pk_logmnr_t1 primary key(a);
表已更改。
SQL>  select supplemental_log_data_min min,supplemental_log_data_pk pk,supplemental_log_data_ui ui,supplemental_log_data_fk fk,supplemental_l
og_data_all from v$database;
MIN      PK  UI  FK  SUP
-------- --- --- --- ---
IMPLICIT YES NO  NO  NO
update logmnr_test set b=77 where c=3;
在结果中会看到
c没有在redo中
update没有涉及主键中的任何列,都强制记录到日志中。
八 设置数据库及unique追加日志
1删除主键追加
alter database drop supplemental log data(primary key) columns;
库已更改。
2增加unique的日志追加模式
SQL> alter database add supplemental log data(unique)columns;
数据库已更改。
SQL> select supplemental_log_data_min min from v$database;
MIN
--------
IMPLICIT
SQL> select supplemental_log_data_ui from v$database;
SUP
---
YES
SQL> select supplemental_log_data_pk from v$database;
SUP
---
NO
SQL> select supplemental_log_data_all from v$database;
SUP
---
NO
SQL> create table logmnr_test1(a int,b int,c int ,d int);
表已创建。
SQL> create unique index idx_logmnr_t1 on logmnr_test1(b,d);
索引已创建。
SQL> insert into logmnr_test1 values(1,2,3,4);
SQL> insert into logmnr_test1 values(2,3,4,5);
已创建 1 行。
SQL> insert into logmnr_test1 values(4,5,6,7);
SQL> update logmnr_test1 set b=77 where c=3;
已更新 1 行。
SQL> update logmnr_test1 set a=88 where c=4;
已更新 1 行。
SQL> select * from v$log;
    GROUP#    THREAD#  SEQUENCE#      BYTES    MEMBERS ARC STATUS
---------- ---------- ---------- ---------- ---------- --- ----------------
FIRST_CHANGE# FIRST_TIME
------------- --------------
         1          1         73   52428800          1 NO  CURRENT
       812295 12-4月 -14


         2          1         71   52428800          1 YES INACTIVE
       787987 11-4月 -14


         3          1         72   52428800          1 YES INACTIVE
       788109 11-4月 -14

SQL> alter system switch logfile;
系统已更改。
exec dbms_logmnr.add_logfile('D:\oracle\product\10.2.0\oradata\ocm\redo01.log',dbms_logmnr.new);
  exec dbms_logmnr.start_logmnr(options=>dbms_logmnr.dict_from_online_catalog+dbms_logmnr.print_pretty_sql);

  SQL_REDO                                           SQL_UNDO
-------------------------------------------------- -----------------------------------------------
    "B" = 5,                                           "B" = 5 and
    "C" = 6,                                           "C" = 6 and
    "D" = 7;                                           "D" = 7 and
                                                       ROWID = 'AAAMm4AABAAAqQqAAC';


update "SYS"."LOGMNR_TEST1"                        update "SYS"."LOGMNR_TEST1"
  set                                                set
    "B" = 77                                           "B" = 2
  where                                              where
    "B" = 2 and                                        "B" = 77 and
    "D" = 4 and                                        "D" = 4 and


SQL_REDO                                           SQL_UNDO
-------------------------------------------------- -----------------------------------------------
    ROWID = 'AAAMm4AABAAAqQqAAA';                      ROWID = 'AAAMm4AABAAAqQqAAA';


update "SYS"."LOGMNR_TEST1"                        update "SYS"."LOGMNR_TEST1"
  set                                                set
    "A" = 88                                           "A" = 2
  where                                              where
    "A" = 2 and                                        "A" = 88 and
    ROWID = 'AAAMm4AABAAAqQqAAB';                      ROWID = 'AAAMm4AABAAAqQqAAB';

我们看到两条update语句,第一条是由b d两列作为条件,第二个update语句是a作为条件,因为第一条sql更改了b的字段,第二条没有涉及到bd

总结:unique是一种条件模式,当联合唯一索引的列发生更改时会记录联合唯一索引的所有列,而上一节测试的primary key是一种无条件模式

关于数据库级别的日志追加模式,还有其他几种情况 

例如:
all无条件模式,记录所有列
foreign key有条件模式,记录外键列
 
九表级别定义的追加日志组(有条件)
首先去除数据库级别的unique日志追加模式
SQL> alter database drop supplemental log data(unique)columns;
数据库已更改。
SQL> alter database add supplemental log data;
数据库已更改。
 select supplemental_log_data_min min,supplemental_log_data_pk pk,supplemental_log_data_ui ui,supplemental_log_data_fk fk,supplemental_log_data_all "all" from v$database;
 MIN      PK  UI  FK  all
-------- --- --- --- ---
YES      NO  NO  NO  NO

设置要记录补充日志的列的组合
SQL> alter table logmnr_test1 add supplemental log group lg_test1(a,b);
表已更改。
SQL> select * from dba_log_groups;
OWNER                          LOG_GROUP_NAME                 TABLE_NAME                     LOG_GROUP_TYPE      ALWAYS      GENERATED
------------------------------ ------------------------------ ------------------------------ ------------------- ----------- ------------
SYS                            LG_TEST1                       LOGMNR_TEST1                   USER LOG GROUP      CONDITIONAL USER NAME
SQL> select * from dba_log_group_columns;

OWNER      LOG_GROUP_NAME       TABLE_NAME           COLUMN_NAM   POSITION LOGGIN
---------- -------------------- -------------------- ---------- ---------- ------
SYS        LG_TEST1             LOGMNR_TEST1         A 1 LOG
SYS        LG_TEST1             LOGMNR_TEST1         B                   2 LOG

SQL> update logmnr_test1 set b=77 where c=3;
已更新 1 行。
SQL> update logmnr_test1 set d=88 where c=4;
已更新 1 行。
SQL> commit;
SQL> select * from v$log;
    GROUP#    THREAD#  SEQUENCE#      BYTES    MEMBERS ARC STATUS           FIRST_CHANGE# FIRST_TIME
---------- ---------- ---------- ---------- ---------- --- ---------------- ------------- --------------
         1          1         73   52428800          1 YES INACTIVE                812295 12-4月 -14
         2          1         74   52428800          1 YES INACTIVE                816942 12-4月 -14
         3          1         75   52428800          1 NO  CURRENT                 817223 12-4月 -14
SQL> alter system switch logfile;
系统已更改。
exec dbms_logmnr.add_logfile('D:\oracle\product\10.2.0\oradata\ocm\redo03.log',dbms_logmnr.new);
exec dbms_logmnr.start_logmnr(options=>dbms_logmnr.dict_from_online_catalog+dbms_logmnr.print_pretty_sql);
 select sql_redo,sql_undo from v$logmnr_contents where seg_name='LOGMNR_TEST1';

SQL_REDO                                           SQL_UNDO
-------------------------------------------------- --------------------------------------------------
alter table logmnr_test1 add supplemental log grou
p lg_test1(a,b);

update "SYS"."LOGMNR_TEST1"                        update "SYS"."LOGMNR_TEST1"
  set                                                set
    "B" = 77                                           "B" = 77
  where                                              where
    "A" = 1 and                                        "A" = 1 and
    "B" = 77 and                                       "B" = 77 and
    ROWID = 'AAAMm4AABAAAqQqAAA';                      ROWID = 'AAAMm4AABAAAqQqAAA';

SQL_REDO                                           SQL_UNDO
-------------------------------------------------- --------------------------------------------------
update "SYS"."LOGMNR_TEST1"                        update "SYS"."LOGMNR_TEST1"
  set                                                set
    "D" = 88                                           "D" = 5
  where                                              where
    "D" = 5 and                                        "D" = 88 and
    ROWID = 'AAAMm4AABAAAqQqAAB';                      ROWID = 'AAAMm4AABAAAqQqAAB';


第1条,满足条件了,因为b包含在日志组(a,b)中 
所以第1条,日志组会记录到REDO中 
而第2条,d=88 
没有在日志组中,没有满足条件 
不记录REDO 

十表级别用户定义的追加日志组(无条件)
先删除前面的有条件日志组的补充日志
SQL> alter table logmnr_test1 drop supplemental log group lg_test1;
表已更改。
SQL> alter table logmnr_test1 add supplemental log group lg_test1(a,b)always;
表已更改。
这个就是无条件附加这两个列了。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值