电梯
Oracle技术嘉年华的一个案例,redo的那些事,连载一Oracle技术嘉年华的一个案例,redo的那些事,连载二在上一篇中,修改
row flag后,
logminer已经可以正确的解析日志了,那么,这个问题是否可以重现呢?我们来做个测试。
由于没有
9i环境,我们使用
11g环境进行测试,测试结果稍微有些偏差,但不影响结论
首先,我们建立
varchar2(4000)类型的三条数据,然后,对这三条数据进行修改,将
4000字节全部占满,那么,必然有一条记录将发生迁移。
SQL*Plus: Release 11.2.0.3.0 Production on Fri Oct 28 08:34:33 2011Copyright (c) 1982, 2011, Oracle. All rights reserved.SQL> conn / as sysdbaConnected.SQL> create table t (a varchar2(4000));Table created.SQL> insert into t values ('a');1 row created.SQL> insert into t values ('b'); 1 row created.SQL> insert into t values ('c'); 1 row created.SQL> SQL> commit;Commit complete.SQL> select t.rowid from t;ROWID------------------AAADZiAABAAAIDBAAAAAADZiAABAAAIDBAABAAADZiAABAAAIDBAACSQL> update t set t.a=lpad('a',4000,'a') where t.a='a';1 row updated.SQL> update t set t.a=lpad('b',4000,'b') where t.a='b';1 row updated.SQL> update t set t.a=lpad('c',4000,'c') where t.a='c';1 row updated.SQL> commit;Commit complete.SQL> select t.rowid from t;ROWID------------------AAADZiAABAAAIDBAAAAAADZiAABAAAIDBAABAAADZiAABAAAIDBAAC应该是
AAADZiAABAAAIDBAAC这条记录发生了迁移,我们看一下数据的物理位置,并将这部分记录
dump出来
SQL> select dbms_rowid.rowid_relative_fno('AAADZiAABAAAIDBAAA') || '.' || dbms_rowid.rowid_block_number('AAADZiAABAAAIDBAAA') from dual 2 3 ;DBMS_ROWID.ROWID_RELATIVE_FNO('AAADZIAABAAAIDBAAA')||'.'||DBMS_ROWID.ROWID_BLOCK--------------------------------------------------------------------------------1.32961SQL> alter system dump datafile 1 block 32961;System altered.对于这条记录,会在两次
dump中出现,首先是行头,它没有数据,但记录了数据的偏移地址
nridtab 0, row 2, @0x3ctl: 9 fb: --H----- lb: 0x2 cc: 0nrid: 0x004080c2.0SQL> alter system dump datafile 1 block 32962;System altered.真正的数据在这里,同时,也记录了行头的偏移地址
hridtab 0, row 0, @0xfdctl: 4012 fb: ----FL-- lb: 0x1 cc: 1 --row flag是
----FL--,也就是
0x0chrid: 0x004080c1.2col 0: [4000]63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63我们对这条记录做一下修改操作,模拟一下案例发生时的情况:
SQL> select dbms_flashback.get_system_change_number from dual;GET_SYSTEM_CHANGE_NUMBER------------------------ 278206SQL> update t set t.a='d' where t.rowid='AAADZiAABAAAIDBAAC';1 row updated.SQL> commit;Commit complete.SQL> select dbms_flashback.get_system_change_number from dual;GET_SYSTEM_CHANGE_NUMBER------------------------ 278213SQL> begin dbms_logmnr.add_logfile('/u01/app/oracle/oradata/ORAVM/redo01.log');end;/PL/SQL procedure successfully completed.SQL> begin dbms_logmnr.start_logmnr(startScn => 278206,endScn => 278213);end;/PL/SQL procedure successfully completed.SQL> select * from v$logmnr_contents t;no rows selected与案例不同的是,在
11g中,已经不会出现
Unsupported记录了,直接就不显示这条记录了。同样,我们做一下
logfile dump,看看
redo log里到底是怎么记录的
SQL> alter system dump logfile '/u01/app/oracle/oradata/ORAVM/redo01.log';System altered.CHANGE #1 TYP:0 CLS:22 AFN:3 DBA:0x00c0096c OBJ:4294967295 SCN:0x0000.00043ec4 SEQ:1 OP:5.1 ENC:0 RBL:0ktudb redo: siz: 4080 spc: 7722 flg: 0x0022 seq: 0x0021 rec: 0x05 xid: 0x0003.00d.000000cdktubu redo: slt: 13 rci: 4 opc: 11.1 objn: 13922 objd: 13922 tsn: 0Undo type: Regular undo Undo type: Last buffer split: NoTablespace Undo: No 0x00000000KDO undo record:KTB Redoop: 0x03 ver: 0x01compat bit: 4 (post-11) padding: 1op: ZKDO Op code: URP row dependencies Disabled xtype: XA flags: 0x00000000 bdba: 0x004080c2 hdba: 0x004080c0itli: 2 ispac: 0 maxfr: 4863tabn: 0 slot: 0(0x0) flag: 0x0c lock: 0 ckix: 0ncol: 1 nnew: 1 size: 4001col 0: [4000]63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63......CHANGE #2 TYP:2 CLS:1 AFN:1 DBA:0x004080c2 OBJ:13922 SCN:0x0000.00043def SEQ:5 OP:11.5 ENC:0 RBL:0KTB Redoop: 0x11 ver: 0x01compat bit: 4 (post-11) padding: 1op: F xid: 0x0003.00d.000000cd uba: 0x00c0096c.0021.05Block cleanout record, scn: 0x0000.00043ec2 ver: 0x01 opt: 0x02, entries follow... itli: 1 flg: 2 scn: 0x0000.00043defKDO Op code: URP row dependencies Disabled xtype: XA flags: 0x00000000 bdba: 0x004080c2 hdba: 0x004080c0itli: 2 ispac: 0 maxfr: 4863tabn: 0 slot: 0(0x0) flag: 0x0c lock: 2 ckix: 0ncol: 1 nnew: 1 size: -4001col 0: [ 1] 64与案例相同,
logminer无法正确解析,但通过
logfile dump,可以看到
redo文件中是包含这部分更新的内容的。
11g与9i不同的地方,9i不会记录OBJ,而11g记录了OBJ,虽然这个OBJ也不对。但这并不影响我们的结论按照
Oracle文档中的指示,我们需要开启附加日志,才可以使
logmminer正确的解析,我们来测试一下。
SQL> alter database add supplemental log data;Database altered.Logminer过程略过
……SQL> select t.RBABLK,t.RBABYTE,t.DATA_OBJ#,t.ROW_ID,t.OPERATION,t.SQL_REDO,t.INFO from v$logmnr_contents t ;13159 16 13922 AAADZiAABAAAIDBAAC UPDATE update "UNKNOWN"."OBJ# 13922" set "COL 1" = HEXTORAW('656565') where "COL 1" = HEXTORAW('64') and ROWID = 'AAADZiAABAAAIDBAAC'; Dictionary MismatchLogminer确实可以正确的解析了。
最后,我们来看一下,在开启附加日志后,
Oracle到底多记录了什么东西,使
logminer可以正确的解析呢?
下面是开启附加日志后,
OP:5.1部分的内容,请大家注意看红色部分,这部分内容在未开启附加日志的
redo log中是找不到的
05 01 20 00 03 00 ff ff fa 00 c0 00 67 43 04 00 00 00 00 00 01 00 ff ff 10 00 14 00 18 00 20 00 1d 00 02 00 01 00 1c 00 8c 00 a4 1c 22 00 00 00 08 00 01 00 cd 00 00 00 2c 00 06 00 62 36 00 00 62 36 00 00 00 00 00 00 00 00 00 00 0b 01 01 05 00 00 cd 00 04 0d 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 00 00 00 00 00 00 c2 80 40 00 c0 80 40 00 ff 12 25 01 03 00 00 00 0c 00 00 00 00 00 01 01 fe ff 00 00 00 0c 40 00 00 00 40 00 64 12 02 01 01 04 00 00 01 00 01 00 01 00 00 00 00 10 00 00 00 00 00 00 c1 80 40 00 02 00 00 00
这部分的内容是不是很眼熟?看看下面这段就明白了,红色这部分内容对应的就是
hrid:
tab 0, row 0, @0xfdctl: 4012 fb: ----FL-- lb: 0x1 cc: 1 --row flag是
----FL--,也就是
0x0chrid: 0x004080c1.2col 0: [4000]63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63没错,在开启附加日志后,对于行迁移数据,
Oracle会将
hrid信息记录下来,这样,我们便可以根据
hrid找到行头,同时,可以计算出正确的
ROWID信息。这部分的内容,同时也证明了我们对于
eygle大师这个案例为什么无法使用
logminer解析的猜想。[@more@]
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/19423/viewspace-1056063/
,如需转载,请注明出处,否则将追究法律责任。