您好,欢迎访问一九零五行业门户网

深入解析Oracle IMU模式下的REDO格式

这个话题讨论在itpub,链接:http://www.itpub.net/thread-1838538-1-1.html 1. 什么是imu?imu的主要作用是什么,也就是说为了解决什么问题? imu---in memory undo,10g新特性,数据库会在shared pool开辟独立的内存区域用于存储undo信息, 每个新事务都会
这个话题讨论在itpub,链接:http://www.itpub.net/thread-1838538-1-1.html
1. 什么是imu?imu的主要作用是什么,也就是说为了解决什么问题?imu--->in memory undo,10g新特性,数据库会在shared pool开辟独立的内存区域用于存储undo信息,
每个新事务都会分配一个imu buffer(私有的),一个buffer里有很多node,一个node相当于一个block(回滚块)。
imu特性:
imu顾名思义就是在内存中的undo,现在每次更改data block,oracle 不用去更改这个undo block(也不会生成相应的redo了),而是把undo信息缓存到imu里去了,只有最后commit或者flush imu时,这些undo 信息才会批量更新到undo block,并生成redo。可以避免undo信息以前在buffer cache中的读写操作,从而可以进一步的减少redo生成,同时可以大大减少以前的undo segment的操作。imu中数据通过暂存、整理与收缩之后也可以写出到回滚段,这样的写出提供了有序、批量写的性能提升。
imu主要作用:
减少cr块-->在构造cr block时,不用像以前那样从undo block中获取undo record了,而是用共享池私有imu区域里的信息来构造cr block,减少了buffer caceh中 cbc latch竞争。
减少redo日志条目数-->不再是每条dml语句一个redo records,而是每个事务一个redo records--redo record的产生会传到 log buffer,,会申请latch。
减少latch-->首先因为减少redo record数目;其次用一个imu latch 代替 redo allocation latch 和 redo copy latch这两个,也减少了latch争用.
查询系统中imu latch的数量--也就是private redo strand area的个数。
imu 私有redo区对应的内部表:x$kcrfstrand       imu undo区对应的内部表:x$ktifp
bys@ bys3>select count(name) from v$latch_children where lower(name) like 'in mem%';
count(name)
-----------
         84
bys@ bys3>select count(*),name from v$latch_children where lower(name) like 'in mem%' group by name;
  count(*) name
---------- ----------------------------------------------------------------
        84 in memory undo latch
下面语句可以查询imu latch的获取情况
select name,gets from v$latch_children where lower(name) like 'in mem%';
2.在哪些场景下不会使用imu特性?(oracle 10g出现了imu,默认开启imu)
在rac环境中不支持imu。
开启flashback database时会开启打开辅助日志,此时不能用imu。
事务过大--据说每个imu buffer的private redo strand area大小大概是64kb(64位的oracle版本是128kb),大事务不能用。比如一个事务,先有一条update,此时将redo私有区域使用完了,此事务的其它dml语句,将自动使用非imu模式。
共享池太小时,oracle会自动不使用imu。
无法获取imu latch时,将自动使用非imu模式。
3.如何手动关闭和开启imu模式?
10g和11g中默认是开启imu特性的,开启关闭语句如下:--修改后最好重启使之生效,或者至少切换一次redo日志。
alter system set _in_memory_undo=false;
alter system set _in_memory_undo=true;  --关闭imu后使用此语句改回使用imu特性。
4、谈谈一条update语句从第一步到第九步的整个过程?在imu模式下对redo日志做dump分析(上图所示:imu模式的redo格式)。update语句从第一步到第九步的对应上图是:第一步:将更改的数据存放到pga 
第二步:将buffer cache中旧数据拷贝到共享池的私有imu buffer
第三步:将pga中修改后的数据存放到private redo   private redo--在imu中才有。
第四步:修改buffre cache中的数据
做提交操作后:
第五步:从imu中拷贝修改前值到buffer cache中构建一个cr块-----即使未提交时smon每3秒也会做此工作
第六步:第四步修改修改buffre cache中的数据产生的redo日志写入log buffe
第七步:第五步操作构造cr块,产生的redo日志写入 log buffe
第八步:由lgwr写出log buffer到redo log file
第九步:dbwr 将脏数据写入data file5.update操作dump redo 内容实验记录:
insert 和delete语句的,详见:点击打开链接
redo record - thread:1 rba: 0x000141.00000027.0010 len: 0x031c vld: 0x0d
scn: 0x0000.00719188 subscn:  1 01/07/2014 20:27:05
(lwn rba: 0x000141.00000027.0010 len: 0002 nst: 0001 scn: 0x0000.00719187)
####一个redo record: record头+change vector组成(一个cv就是一个操作)
以上是日志头,thread:1 线程号,rac时会有1,2等
rba: 0x000141.00000027.0010 将16进制转换为十进制分别是日志文件号、日志块号、在块上第n字节
vld: 0x0d日志类型--imu模式时是这个;非imu时是:vld: 0x05
scn: 0x0000.00719188 subscn:  1 01/07/2014 20:27:05   ----
bys@ bys3>select scn_to_timestamp(to_number('719188','xxxxxxxx')) from dual;
scn_to_timestamp(to_number('719188','xxxxxxxx'))
---------------------------------------------------------------------------
07-jan-14 08.27.05.000000000 pm
--是此redo条目产生时的scn号,转为十进制现转为时间戳为:08.27.05, 插入语句完成是在20:27:00 bys@ bys3>commit;--  --这个是在插入语句完成5秒后,此scn与change#4提交时scn一致。
(lwn rba: 0x000141.00000027.0010 len: 0002 nst: 0001 scn: 0x0000.00719187)
括号中scn: 0x0000.00719187 比上一行:scn: 0x0000.00719187   少了1个scn。
####
change #1 typ:2 cls:1 afn:4 dba:0x010000fd obj:22327 scn:0x0000.007164a1 seq:1 op:11.5 enc:0 rbl:0
#####afn:4,操作是在4号文件做的-dba_data_files.file_id;obj:22327--操作的对象的object_id。op:11.5-有的版本是op:11.19--更新操作
ktb redo
op: 0x11  ver: 0x01
compat bit: 4 (post-11) padding: 1
op: f  xid:  0x0005.002.00000edc    uba: 0x00c041cd.02ea.01
block cleanout record, scn:  0x0000.0071917c ver: 0x01 opt: 0x02, entries follow...
  itli: 1  flg: 2  scn: 0x0000.007164a1
kdo op code: urp row dependencies disabled   -- --urp=update row piece。有时会是:kdo op code:21 row dependencies disabled
  xtype: xa flags: 0x00000000  bdba: 0x010000fd  hdba: 0x010000fa
itli: 2  ispac: 0  maxfr: 4858
tabn: 0 slot: 8(0x8) flag: 0x2c lock: 2 ckix: 0
ncol: 3 nnew: 1 size: 2   --ncol: 3 nnew: 1  表示操作的表有3个列,操作了一列,size: 2
--列字符长度增加2:database减去chedan---根据多次update并dump的日志来看,这里的size的值应该是:当前change中的值减去另一个。。
col  1: [ 8]  64 61 74 61 62 61 73 65   --set dname='database'  --col  1: [ 8],第二列,8个字符
bys@ bys3>select dump('database',16),dump('dataoracle',16) from dual;
dump('database',16)                   dump('dataoracle',16)
------------------------------------- --------------------------------------------
typ=96 len=8: 64,61,74,61,62,61,73,65 typ=96 len=10: 64,61,74,61,6f,72,61,63,6c,65
#########################
change #2 typ:0 cls:25 afn:3 dba:0x00c000c0 obj:4294967295 scn:0x0000.00719153 seq:1 op:5.2 enc:0 rbl:0
ktudh redo: slt: 0x0002 sqn: 0x00000edc flg: 0x000a siz: 164 fbi: 0
            uba: 0x00c041cd.02ea.01    pxid:  0x0000.000.00000000
### #####################事务信息
typ:0 普通块 ,cls:25 class大于16是undo块-递增。afn:3 绝对文件号dba_data_files.file_id--是undo的文件号
dba:0x00c000c0 数据块在内存中地址
obj:4294967295 --十进制,转为16进制是ffffffff
scn:0x0000.00719153  转换为16进制可与操作时对比
op:5.2 -> operation code 向undo段头的事务表写事务信息-事务开始
uba: 0x00c041cd.02ea.01  undo块地址
#######################
change #3 typ:0 cls:1 afn:4 dba:0x010000fdobj:22327 scn:0x0000.00719188 seq:1op:11.5 enc:0 rbl:0
ktb redo        --同change #1的解析
op: 0x02  ver: 0x01
compat bit: 4 (post-11) padding: 1
op: c  uba: 0x00c041cd.02ea.02
kdo op code: urp row dependencies disabled   ---undo row piece
  xtype: xa flags: 0x00000000  bdba: 0x010000fd  hdba: 0x010000fa
itli: 2  ispac: 0  maxfr: 4858
tabn: 0 slot: 9(0x9) flag: 0x2c lock: 2 ckix: 0
ncol: 3 nnew: 1 size: 6
col  1: [10]  64 61 74 61 6f 72 61 63 6c 65   --第2列,10个字符--此次操作的字符数
bys@ bys3>select dump('database',16),dump('dataoracle',16) from dual;
dump('database',16)                   dump('dataoracle',16)
------------------------------------- --------------------------------------------
typ=96 len=8: 64,61,74,61,62,61,73,65 typ=96 len=10: 64,61,74,61,6f,72,61,63,6c,65
###########################
change #4 typ:0 cls:25 afn:3dba:0x00c000c0 obj:4294967295scn:0x0000.00719188 seq:1 op:5.4 enc:0 rbl:0
ktucm redo: slt: 0x0002 sqn: 0x00000edc srt: 0 sta: 9 flg: 0x2 ktucf redo: uba: 0x00c041cd.02ea.02 ext: 15 spc: 7890 fbi: 0
######op:5.4 表明是提交操作。afn:3 对应的是undo文件,slt: 0x0002  修改了undo文件的这个事务槽,uba: 0x00c041cd.02ea.02
change #5 typ:1 cls:26 afn:3 dba:0x00c041cd obj:4294967295 scn:0x0000.0071917c seq:1 op:5.1 enc:0 rbl:0
ktudb redo: siz: 164 spc: 0 flg: 0x000a seq: 0x02ea rec: 0x01
###op:5.1 --把数据修改前值放到undo   --afn:3 --在undo文件里操作,undo文件号是3。。cls:26 --比change #2中大1,顺序增长哈哈
            xid:  0x0005.002.00000edc
ktubl redo: slt: 2 rci: 0 opc: 11.1 [objn: 22327 objd: 22327 tsn: 4]
undo type:  regular undo        begin trans    last buffer split:  no
temp object:  no
tablespace undo:  no
             0x00000000  prev ctl uba: 0x00c041cc.02ea.04
prev ctl max cmt scn:  0x0000.00718dff  prev tx cmt scn:  0x0000.00718e4e
txn start scn:  0x0000.00000000  logon user: 32  prev brb: 12599753  prev bcl: 0 buext idx: 0 flg2: 0
kdo undo record:
ktb redo
op: 0x04  ver: 0x01
compat bit: 4 (post-11) padding: 1
op: l  itl: xid:  0x0009.004.00000ebc uba: 0x00c037d5.0249.08
                      flg: c---    lkc:  0     scn: 0x0000.0070cfea
kdo op code: urp row dependencies disabled   -----undo row piece
  xtype: xa flags: 0x00000000  bdba: 0x010000fd  hdba: 0x010000fa
itli: 2  ispac: 0  maxfr: 4858
tabn: 0 slot: 8(0x8) flag: 0x2c lock: 0 ckix: 0
ncol: 3 nnew: 1 size: -2    ----列字符长度减少2:chedan 减去database---根据多次update并dump的日志来看,这里的size的值应该是:当前change中的值减去另一个
col  1: [ 6]  63 68 65 64 61 6e   ----  原值是chedan,,第二列,6个字符
bys@ bys3>select dump('chedan',16),dump('test',16) from dual;
dump('chedan',16)               dump('test',16)
------------------------------- -------------------------
typ=96 len=6: 63,68,65,64,61,6e typ=96 len=4: 74,65,73,74
change #6 typ:0 cls:26 afn:3 dba:0x00c041cd obj:4294967295 scn:0x0000.00719188 seq:1 op:5.1enc:0 rbl:0  --解析同上
ktudb redo: siz: 92 spc: 7984 flg: 0x0022 seq: 0x02ea rec: 0x02
            xid:  0x0005.002.00000edc
ktubu redo: slt: 2 rci: 1 opc: 11.1 objn: 22327 objd: 22327 tsn: 4
undo type:  regular undo       undo type:  last buffer split:  no
tablespace undo:  no
             0x00000000
kdo undo record:
ktb redo
op: 0x02  ver: 0x01
compat bit: 4 (post-11) padding: 1
op: c  uba: 0x00c041cd.02ea.01
kdo op code: urp row dependencies disabled     -----undo row piece
  xtype: xa flags: 0x00000000  bdba: 0x010000fd  hdba: 0x010000fa
itli: 2  ispac: 0  maxfr: 4858
tabn: 0 slot: 9(0x9) flag: 0x2c lock: 0 ckix: 0
ncol: 3 nnew: 1 size: -6    -列字符长度减少2:test减去database---根据多次update并dump的日志来看,这里的size的值应该是:当前change中的值减去另一个
col  1: [ 4]  74 65 73 74     --此次操作,第二列,4个字符
bys@ bys3>select dump('chedan',16),dump('test',16) from dual;
dump('chedan',16)               dump('test',16)
------------------------------- -------------------------
typ=96 len=6: 63,68,65,64,61,6e typ=96 len=4: 74,65,73,74
################################################验证smon进程
实验步骤: --这个实验思路有错误的。不应该是dmup redo日志,因为当时还没从log buffe写入redo log file,可以考虑使用--我还未做。
event 10500 - trace smon process 跟踪smon进程 event = 10500 trace name context forever, level 1    d
12:12:04 bys@ bys3>select a.group#,a.sequence#,a.archived,a.status,b.type,b.member from v$log a,v$logfile b where a.group#=b.group#;
group#  sequence# arc status           type    member
---------- ---------- --- ---------------- ------- ------------------------------
         1        334 no  current          online  /u01/oradata/bys3/redo01.log
         2        332 yes active           online  /u01/oradata/bys3/redo02.log
         3        333 yes active           online  /u01/oradata/bys3/redo03.log
elapsed: 00:00:00.03
12:12:09 bys@ bys3>select * from dept;
    deptno dname          loc
---------- -------------- -------------
        10 accounting     new york
        20 research       dallas
        40 operations     boston
        11 database       database
        22 dataoracle     sh
elapsed: 00:00:00.01
12:12:24 bys@ bys3>update dept set dname='mysql' where deptno=11;
1 row updated.
elapsed: 00:00:00.01
12:12:29 bys@ bys3>   ---update语句完成的时间是:12:12:29,只做update语句,不要提交,立刻去dump redo logfile.
另一会话在上一步做操作时来dump  :  event = 10500 trace name context forever, level 1
其它类似信息

推荐信息