ITPub博客

首页 > 数据库 > Oracle > Oracle技术嘉年华的一个案例,redo的那些事,连载三

Oracle技术嘉年华的一个案例,redo的那些事,连载三

原创 Oracle 作者:sundog315 时间:2011-10-31 16:15:37 0 删除 编辑
电梯
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 2011

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

SQL> conn / as sysdba
Connected.
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
------------------
AAADZiAABAAAIDBAAA
AAADZiAABAAAIDBAAB
AAADZiAABAAAIDBAAC

SQL> 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
------------------
AAADZiAABAAAIDBAAA
AAADZiAABAAAIDBAAB
AAADZiAABAAAIDBAAC

应该是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.32961

SQL> alter system dump datafile 1 block 32961;

System altered.

对于这条记录,会在两次dump中出现,首先是行头,它没有数据,但记录了数据的偏移地址nrid

tab 0, row 2, @0x3c
tl: 9 fb: --H----- lb: 0x2 cc: 0
nrid: 0x004080c2.0
SQL> alter system dump datafile 1 block 32962;

System altered.

真正的数据在这里,同时,也记录了行头的偏移地址hrid

tab 0, row 0, @0xfdc
tl: 4012 fb: ----FL-- lb: 0x1 cc: 1 --row flag是----FL--,也就是0x0c
hrid: 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
------------------------
278206

SQL> 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
------------------------
278213

SQL> 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:0
ktudb redo: siz: 4080 spc: 7722 flg: 0x0022 seq: 0x0021 rec: 0x05
xid: 0x0003.00d.000000cd
ktubu redo: slt: 13 rci: 4 opc: 11.1 objn: 13922 objd: 13922 tsn: 0
Undo type: Regular undo Undo type: Last buffer split: No
Tablespace Undo: No
0x00000000
KDO undo record:
KTB Redo
op: 0x03 ver: 0x01
compat bit: 4 (post-11) padding: 1
op: Z
KDO Op code: URP row dependencies Disabled
xtype: XA flags: 0x00000000 bdba: 0x004080c2 hdba: 0x004080c0
itli: 2 ispac: 0 maxfr: 4863
tabn: 0 slot: 0(0x0) flag: 0x0c lock: 0 ckix: 0
ncol: 1 nnew: 1 size: 4001
col 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:0
KTB Redo
op: 0x11 ver: 0x01
compat bit: 4 (post-11) padding: 1
op: F xid: 0x0003.00d.000000cd uba: 0x00c0096c.0021.05
Block cleanout record, scn: 0x0000.00043ec2 ver: 0x01 opt: 0x02, entries follow...
itli: 1 flg: 2 scn: 0x0000.00043def
KDO Op code: URP row dependencies Disabled
xtype: XA flags: 0x00000000 bdba: 0x004080c2 hdba: 0x004080c0
itli: 2 ispac: 0 maxfr: 4863
tabn: 0 slot: 0(0x0) flag: 0x0c lock: 2 ckix: 0
ncol: 1 nnew: 1 size: -4001
col 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 Mismatch

Logminer确实可以正确的解析了。

最后,我们来看一下,在开启附加日志后,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, @0xfdc
tl: 4012 fb: ----FL-- lb: 0x1 cc: 1 --row flag是----FL--,也就是0x0c
hrid: 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/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2010-01-05

  • 博文量
    126
  • 访问量
    540253