Skip to content

实验内容:非IMU模式下DML语句产生的REDO日志内容格式解读,数据库版本:11.2.0.4
最详细的解读是UPDATE的。
实验环境准备
11G中默认是开启IMU特性的,做此实验需要关闭此特性。
alter system set “_in_memory_undo”=false;
alter system set “_in_memory_undo”=true; –实验结束后使用此语句改回使用IMU特性。
修改参数完成后,重启数据库:
shutdown immediate;
startup;
准备好实验用的表—-BYS.DEPT表。
SYS@ bys3>select object_id from dba_objects where object_name=’DEPT’;
OBJECT_ID
———-
22327
SYS@ bys3>select * from bys.dept;
DEPTNO DNAME LOC
———- ————– ————-
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
40 OPERATIONS BOSTON
11 chedan bj
22 test sh
BYS@ bys3>col file_name for a35
SYS@ bys3>col name for a15
SYS@ bys3> select a.file_id,b.ts#,b.name,a.file_name from dba_data_files a,v$tablespace b where a.TABLESPACE_NAME=b.name;
FILE_ID TS# NAME FILE_NAME
———- ———- ————— ———————————–
1 0 SYSTEM /u01/oradata/bys3/system01.dbf
2 1 SYSAUX /u01/oradata/bys3/sysaux01.dbf
3 2 UNDOTBS1 /u01/oradata/bys3/undotbs01.dbf
4 4 USERS /u01/oradata/bys3/user01.dbf
###################################################
开始实验分三步,分别是插入、更新、删除语句的操作。 最详细的解读是UPDATE的。
实验一:insert 操作的REDO日志解读
会话1: –SYS用户切换日志并查出当前日志名:
SYS@ bys3>alter system switch logfile;
System altered.
col MEMBER for a30
SYS@ 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 310 NO CURRENT ONLINE /u01/oradata/bys3/redo01.log
2 308 YES INACTIVE ONLINE /u01/oradata/bys3/redo02.log
3 309 YES ACTIVE ONLINE /u01/oradata/bys3/redo03.log
普通用户做插入语句:
SYS@ bys3>conn bys/bys
select * from dept;
Connected.
BYS@ bys3>
DEPTNO DNAME LOC
———- ————– ————-
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
40 OPERATIONS BOSTON
11 chedan bj
22 test sh
BYS@ bys3>set time on
20:34:07 BYS@ bys3>insert into dept values(33,’imutest’,’hz’);
1 row created.
20:34:12 BYS@ bys3>commit;
Commit complete.
会话2:DUMP当前REDO日志:
SYS@ bys3>alter system dump logfile ‘/u01/oradata/bys3/redo01.log’;
System altered.
SYS@ bys3>select value from v$diag_info where name like ‘De%’ ;
VALUE
—————————————————————————————————-
/u01/diag/rdbms/bys3/bys3/trace/bys3_ora_29063.trc
######################
查看此TRACE文件: 方法是:vi /u01/diag/rdbms/bys3/bys3/trace/bys3_ora_29063.trc 然后搜索修改的对象的OBJECT_ID– 22327
详解参考下一步的UPDATE的REDO讲解。
REDO RECORD – Thread:1 RBA: 0x000136.0000000d.0010 LEN: 0x01a0 VLD: 0x05
SCN: 0x0000.00702f08 SUBSCN: 1 01/06/2014 20:34:13
(LWN RBA: 0x000136.0000000d.0010 LEN: 0002 NST: 0001 SCN: 0x0000.00702f08)
CHANGE #1 TYP:0 CLS:21 AFN:3 DBA:0x00c000a0 OBJ:4294967295 SCN:0x0000.00702eda SEQ:1 OP:5.2 ENC:0 RBL:0
ktudh redo: slt: 0x0003 sqn: 0x00000eaa flg: 0x0012 siz: 112 fbi: 0
uba: 0x00c01ac7.0250.25 pxid: 0x0000.000.00000000
CHANGE #2 TYP:0 CLS:22 AFN:3 DBA:0x00c01ac7 OBJ:4294967295 SCN:0x0000.00702ed9 SEQ:3 OP:5.1 ENC:0 RBL:0
ktudb redo: siz: 112 spc: 3494 flg: 0x0012 seq: 0x0250 rec: 0x25
xid: 0x0003.003.00000eaa
ktubl redo: slt: 3 rci: 0 opc: 11.1 [ objn: 22327 objd: 22327 tsn: 4] ——- tsn: 4 , 插入的这个是在表空间号为4– OBJ:22327–是插入的对象的OBJECT_ID
Undo type: Regular undo Begin trans Last buffer split: No
Temp Object: No
Tablespace Undo: No
0x00000000 prev ctl uba: 0x00c01ac7.0250.22
prev ctl max cmt scn: 0x0000.007029ac prev tx cmt scn: 0x0000.007029d6
txn start scn: 0xffff.ffffffff logon user: 32 prev brb: 12589763 prev bcl: 0 BuExt idx: 0 flg2: 0
KDO undo record:
KTB Redo
op: 0x03 ver: 0x01
compat bit: 4 (post-11) padding: 1
op: Z
KDO Op code: DRP row dependencies Disabled
xtype: XA flags: 0x00000000 bdba: 0x010000ff hdba: 0x010000fa
itli: 1 ispac: 0 maxfr: 4858
tabn: 0 slot: 0(0x0)
CHANGE #3 TYP:0 CLS:1 AFN:4 DBA:0x010000ff OBJ:22327 SCN:0x0000.003eec75 SEQ:1 OP:11.2 ENC:0 RBL:0 — OP:11.2 这个应该是插入的操作的了。
KTB Redo —– AFN:4, 插入的这个是在4号数据文件中– OBJ:22327–是插入的对象的OBJECT_ID
op: 0x01 ver: 0x01
compat bit: 4 (post-11) padding: 1
op: F xid: 0x0003.003.00000eaa uba: 0x00c01ac7.0250.25
KDO Op code: IRP row dependencies Disabled
xtype: XA flags: 0x00000000 bdba: 0x010000ff hdba: 0x010000fa
itli: 1 ispac: 0 maxfr: 4858
tabn: 0 slot: 0(0x0) size/delt: 17
fb: –H-FL– lb: 0x1 cc: 3
null: —
col 0: [ 2] c1 22 —插入语句是:insert into dept values(33,’imutest’,’hz’); 对应是:select dump(33,16) from dual; –要注意数字在DUMP时不要加单引号
col 1: [ 7] 69 6d 75 74 65 73 74 –对应select dump(‘imutest’,16) from dual; [7]–中括号里的是字节数,col 1:对应的是第二列,
col 2: [ 2] 68 7a —对应 select dump(‘hz’,16) from dual; –中括号里的是字节数 col 2: 对应 的是第三列
select chr(to_number(substr(replace(’69 6d 75 74 65 73 74′,’ ‘),rownum*2-1,2),’xxxxxxxxxxxxxxxx’)) from v$bh where rownum<11;
CHR(
—-
i
m
u
t
e
s
t
REDO RECORD – Thread:1 RBA: 0x000136.0000000d.01b0 LEN: 0x0060 VLD: 0x01
SCN: 0x0000.00702f09 SUBSCN: 1 01/06/2014 20:34:13 —- OP:5.4,提交操作
CHANGE #1 TYP:0 CLS:21 AFN:3 DBA:0x00c000a0 OBJ:4294967295 SCN:0x0000.00702f08 SEQ:1 OP:5.4 ENC:0 RBL:0
ktucm redo: slt: 0x0003 sqn: 0x00000eaa srt: 0 sta: 9 flg: 0x2 ktucf redo: uba: 0x00c01ac7.0250.25ext: 12 spc: 3380 fbi: 0

############################
实验二:update 操作的REDO日志解读
会话3: –SYS用户切换日志:
SYS@ bys3>alter system switch logfile;
System altered.
SYS@ bys3>col MEMBER for a30
SYS@ 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 310 YES ACTIVE ONLINE /u01/oradata/bys3/redo01.log
2 311 NO CURRENT ONLINE /u01/oradata/bys3/redo02.log
3 309 YES INACTIVE ONLINE /u01/oradata/bys3/redo03.log
切换到普通用户做更新语句:
SYS@ bys3>conn bys/bys
Connected.
BYS@ bys3>select * from dept;
DEPTNO DNAME LOC
———- ————– ————-
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
40 OPERATIONS BOSTON
11 chedan bj
22 test sh
33 imutest hz
6 rows selected.
BYS@ bys3>set time on
20:39:23 BYS@ bys3>update dept set dname=’database’ where deptno=11;
1 row updated.
20:39:43 BYS@ bys3>commit;
Commit complete.
20:39:46 BYS@ bys3>

会话4:DUMP当前REDO日志:
SYS@ bys3>alter system dump logfile ‘/u01/oradata/bys3/redo02.log’;
System altered.
SYS@ bys3>select value from v$diag_info where name like ‘De%’ ;
VALUE
—————————————————————————————————-
/u01/diag/rdbms/bys3/bys3/trace/bys3_ora_29141.trc
##############
查看此TRACE文件: 方法是:vi /u01/diag/rdbms/bys3/bys3/trace/bys3_ora_29141.trc 然后搜索修改的对象的OBJECT_ID:22327

UPDATE 一行记录产生一个REDO RECORD,提交产生一个REDO RECORD。非IMU下如果一个UPDATE更新多行,则会产生多条REDO RECORD。关于这个UPDATE语句 产生多少REDO RECORD的话题详见另一篇: 非IMU模式下一条update语句产生REDO RECORD条数的探究
###### 一个REDO RECORD: RECORD头+CHANGE VECTOR组成(一个CV就是一个操作)
REDO RECORD – Thread:1 RBA: 0x000137.00000003.0010 LEN: 0x01ec VLD: 0x05
SCN: 0x0000.00702fe0 SUBSCN: 1 01/06/2014 20:39:45
(LWN RBA: 0x000137.00000003.0010 LEN: 0001 NST: 0001 SCN: 0x0000.00702fdf)
##以上是日志头,Thread:1 线程号,RAC时会有1,2等
RBA: 0x000137.00000003.0010 将16进制转换为十进制分别是日志文件号、日志块号、在块上第N字节
VLD: 0x05日志类型;
SCN: 0x0000.00702fe0 SUBSCN: 1 01/06/2014 20:39:45
–是此REDO条目产生时的SCN号,转为十进制现转为时间戳为:06-JAN-14 08.39.42, 更新语句完成是在20:39:43 BYS@bys3>commit;
(LWN RBA: 0x000137.00000003.0010 LEN: 0001 NST: 0001 SCN: 0x0000.00702fdf)
括号中SCN: SCN: 0x0000.00702fdf 比上一句:SCN: 0x0000.00702fe0 SUBSCN: 1 01/06/2014 20:39:45 少了1个SCN。
######
CHANGE #1 TYP:0 CLS:17 AFN:3 DBA:0x00c00080 OBJ:4294967295 SCN:0x0000.00702f9a SEQ:1 OP:5.2 ENC:0 RBL:0
ktudh redo: slt: 0x000f sqn: 0x00000e9c flg: 0x0012 siz: 164 fbi: 0 –这一行信息与下一条提交的 REDO RECORD可以对上,证明是同一个事务的。
uba: 0x00c01cbf.0250.0f pxid: 0x0000.000.00000000
### ##################### 事务信息
TYP:0 普通块 ,CLS:17 class大于16是UNDO块-递增。AFN:3 绝对文件号dba_data_files.file_id–这里是UNDO文件的文件号
DBA:0x00c00080 数据块在内存中地址, 80十进制128,,select SEGMENT_NAME from dba_segments where HEADER_FILE=3 and HEADER_BLOCK=128; 查出对象名。
OBJ:4294967295 –十进制,转为16进制是FFFFFFFF
SCN:0x0000.00702f9a 转换为16进制可与操作时对比
OP:5.2 -> operation code 向UNDO段头的事务表写事务信息-事务开始
uba: 0x00c01cbf.0250.0f UNDO块地址
####################
CHANGE #2 TYP:0 CLS:18 AFN:3 DBA:0x00c01cbf OBJ:4294967295 SCN:0x0000.00702f99 SEQ:2 OP:5.1 ENC:0 RBL:0
## OP:5.1 –把数据修改前值放到UNDO –AFN:3 –在UNDO文件里操作,UNDO文件号是3。。 CLS:18 –比 CHANGE #1中大1,顺序增长哈哈
ktudb redo: siz: 164 spc: 6494 flg: 0x0012 seq: 0x0250 rec: 0x0f
xid: 0x0001.00f.00000e9c
ktubl redo: slt: 15 rci: 0 opc: 11.1 [objn: 22327 objd: 22327 tsn: 4] ——- tsn: 4, 插入的这个是在表空间号-USERS的表空间号,– OBJ:22327–是插入的对象的OBJECT_ID
Undo type: Regular undo Begin trans Last buffer split: No
Temp Object: No
Tablespace Undo: No
0x00000000 prev ctl uba: 0x00c01cbf.0250.0d
prev ctl max cmt scn: 0x0000.00702afa prev tx cmt scn: 0x0000.00702b2e
txn start scn: 0xffff.ffffffff logon user: 32 prev brb: 12590267 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: 0x0005.008.00000e9d uba: 0x00c01840.02e4.13
flg: C— lkc: 0 scn: 0x0000.00702b1f
KDO Op code: URP row dependencies Disabled
xtype: XA flags: 0x00000000 bdba: 0x010000fd hdba: 0x010000fa
itli: 1 ispac: 0 maxfr: 4858
tabn: 0 slot: 5(0x5) flag: 0x2c lock: 0 ckix: 0
ncol: 3 nnew: 1 size: -2 ##列字符长度减少2: chedan减去database就是-2—根据多次update并DUMP的日志来看,这里的 size的值应该是:当前 CHANGE中的值减去另一个
col 1: [ 6] 63 68 65 64 61 6e –修改语句是:update dept set dname=’database’ where deptno=11; deptno=11时的为chedan-DUMP为16进制,与col 1: [ 6] 63 68 65 64 61 6e对应,[ 6]
与 chedan对应, col 1是第二列–修改的dname列就是第二列。
SYS@ bys3> select dump(‘chedan’,16) from dual;
DUMP(‘CHEDAN’,16)
——————————-
Typ=96 Len=6: 63,68,65,64,61,6e
##############
CHANGE #3 TYP:2 CLS:1 AFN:4DBA:0x010000fd OBJ:22327 SCN:0x0000.00702d7aSEQ:1 OP:11.5 ENC:0 RBL:0
## OP:11.19 或者OP:11.5都是–UPDATE语句,开始修改数据, AFN:4 –这次是在USERS表空间修改数据-文件号就是4
KTB Redo
op: 0x11 ver: 0x01
compat bit: 4 (post-11) padding: 1
op: F xid: 0x0001.00f.00000e9c uba: 0x00c01cbf.0250.0f
Block cleanout record, scn: 0x0000.00702fe0 ver: 0x01 opt: 0x02, entries follow…
itli: 1 flg: 2 scn: 0x0000.00702b1f
itli: 2 flg: 2 scn: 0x0000.00702d7a
KDO Op code: URP row dependencies Disabled
###此语句也说明是UPDATE语句,URP row dependencies Disabled –URP=UPDATE ROW PIECE。有时会是:KDO Op code:21 row dependencies Disabled
xtype: XA flags: 0x00000000 bdba: 0x010000fd hdba: 0x010000fa
itli: 1 ispac: 0 maxfr: 4858
tabn: 0 slot: 5(0x5) flag: 0x2c lock: 1 ckix: 0
ncol: 3 nnew: 1 size: 2 ##size: 2,列字符长度增加2:database减去 chedan—根据多次update并DUMP的日志来看,这里的 size的值应该是:当前 CHANGE中的值减去另一个
col 1: [ 8] 64 61 74 61 62 61 73 65 —update dept set dname=’database’ where deptno=11;,对应 select dump(‘database’,16) from dual; col 1: [ 8] —第二列,8位,
####################################################
REDO RECORD – Thread:1 RBA: 0x000137.00000004.0010 LEN: 0x008c VLD: 0x05
SCN: 0x0000.00702fe2 SUBSCN: 1 01/06/2014 20:39:46
(LWN RBA: 0x000137.00000004.0010 LEN: 0001 NST: 0001 SCN: 0x0000.00702fe1)
CHANGE #1 TYP:0 CLS:17 AFN:3 DBA:0x00c00080 OBJ:4294967295 SCN:0x0000.00702fe0 SEQ:1 OP:5.4 ENC:0 RBL:0
ktucm redo: slt: 0x000f sqn: 0x00000e9c srt: 0 sta: 9 flg: 0x2 ktucf redo: uba: 0x00c01cbf.0250.0f ext: 4 spc: 6328 fbi: 0
###########
OP:5.4 表明是提交操作。
CHANGE #1 TYP:0 CLS:17 AFN:3 DBA:0x00c00080 OBJ:4294967295 SCN:0x0000.00702fe0 SEQ:1 OP:5.4 ENC:0 RBL:0
AFN:3 对应的是UNDO文件,
slt: 0x000f slot是槽位号,slot是每一个事务的入口,在一个事务中是不变的。这里与上一条REDO RECORD中的第一个CHANGE #1中的slt: 0x000f是相同的。

SCN: 0x0000.00702fe2 SUBSCN: 1 01/06/2014 20:39:46 提交操作的时间 :
20:39:43 BYS@ bys3>commit;
Commit complete.
20:39:46 BYS@ bys3>
########################################
实验三:delete 操作的REDO日志解读
会话5: –SYS用户切换日志:
alter system switch logfile;
SYS@ bys3>col member for a30
SYS@ 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 310 YES INACTIVE ONLINE /u01/oradata/bys3/redo01.log
2 311 YES ACTIVE ONLINE /u01/oradata/bys3/redo02.log
3 312 NO CURRENT ONLINE /u01/oradata/bys3/redo03.log
切换到普通用户做删除语句:
conn bys/bys
BYS@ bys3>select * from dept;
DEPTNO DNAME LOC
———- ————– ————-
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
40 OPERATIONS BOSTON
11 database bj
22 test sh
33 imutest hz
6 rows selected.
BYS@ bys3>set time on
20:43:18 BYS@ bys3>delete dept where deptno=33;
1 row deleted.
20:43:25 BYS@ bys3>commit;
Commit complete.
会话6,DUMP当前REDO日志:
SYS@ bys3>alter system dump logfile ‘/u01/oradata/bys3/redo03.log’;
System altered.
SYS@ bys3>select value from v$diag_info where name like ‘De%’ ;
VALUE
—————————————————————————————————-
/u01/diag/rdbms/bys3/bys3/trace/bys3_ora_29214.trc
##############
查看此TRACE文件: 方法是:vi /u01/diag/rdbms/bys3/bys3/trace/bys3_ora_29214.trc 然后搜索修改的对象的OBJECT_ID:22327

REDO RECORD – Thread:1 RBA: 0x000138.0000002b.0010 LEN: 0x01c8 VLD: 0x05
SCN: 0x0000.0070306c SUBSCN: 1 01/06/2014 20:43:26
(LWN RBA: 0x000138.0000002b.0010 LEN: 0002 NST: 0001 SCN: 0x0000.0070306b)
CHANGE #1 TYP:0 CLS:29 AFN:3 DBA:0x00c000e0 OBJ:4294967295 SCN:0x0000.0070303f SEQ:1 OP:5.2 ENC:0 RBL:0
ktudh redo: slt: 0x0008 sqn: 0x00000e9b flg: 0x0012 siz: 168 fbi: 0
uba: 0x00c0193e.02b8.03 pxid: 0x0000.000.00000000
CHANGE #2 TYP:0 CLS:30 AFN:3 DBA:0x00c0193e OBJ:4294967295 SCN:0x0000.0070303e SEQ:1 OP:5.1 ENC:0 RBL:0
ktudb redo: siz: 168 spc: 7794 flg: 0x0012 seq: 0x02b8 rec: 0x03
xid: 0x0007.008.00000e9b
ktubl redo: slt: 8 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: 0x00c0193e.02b8.02
prev ctl max cmt scn: 0x0000.00702b2d prev tx cmt scn: 0x0000.00702b3e
txn start scn: 0xffff.ffffffff logon user: 32 prev brb: 12589367 prev bcl: 0 BuExt idx: 0 flg2: 0
KDO undo record:
KTB Redo
op: 0x03 ver: 0x01
compat bit: 4 (post-11) padding: 1
op: Z
KDO Op code: IRP row dependencies Disabled
xtype: XA flags: 0x00000000 bdba: 0x010000ff hdba: 0x010000fa
itli: 2 ispac: 0 maxfr: 4858
tabn: 0 slot: 0(0x0) size/delt: 17
fb: –H-FL– lb: 0x0 cc: 3
null: —
col 0: [ 2] c1 22 —记录删除前的原值,delete dept where deptno=33; 删除的是这一行值: 33 imutest hz
col 1: [ 7] 69 6d 75 74 65 73 74
col 2: [ 2] 68 7a
###################
BYS@ bys3>select dump(33,16),dump(‘imutest’,16),dump(‘hz’,16) from dual;
DUMP(33,16) DUMP(‘IMUTEST’,16) DUMP(‘HZ’,16)
—————— ———————————- ——————-
Typ=2 Len=2: c1,22 Typ=96 Len=7: 69,6d,75,74,65,73,74 Typ=96 Len=2: 68,7a
#####################

CHANGE #3 TYP:2 CLS:1 AFN:4 DBA:0x010000ff OBJ:22327 SCN:0x0000.00702f09 SEQ:1 OP:11.3 ENC:0 RBL:0
KTB Redo
op: 0x11 ver: 0x01
compat bit: 4 (post-11) padding: 1
op: F xid: 0x0007.008.00000e9b uba: 0x00c0193e.02b8.03
Block cleanout record, scn: 0x0000.0070306c ver: 0x01 opt: 0x02, entries follow…
itli: 1 flg: 2 scn: 0x0000.00702f09
KDO Op code: DRP row dependencies Disabled
xtype: XA flags: 0x00000000 bdba: 0x010000ff hdba: 0x010000fa
itli: 2 ispac: 0 maxfr: 4858
tabn: 0 slot: 0(0x0)

REDO RECORD – Thread:1 RBA: 0x000138.0000002b.01d8 LEN: 0x0060 VLD: 0x01
SCN: 0x0000.0070306d SUBSCN: 1 01/06/2014 20:43:26
CHANGE #1 TYP:0 CLS:29 AFN:3 DBA:0x00c000e0 OBJ:4294967295 SCN:0x0000.0070306c SEQ:1 OP:5.4 ENC:0 RBL:0
ktucm redo: slt: 0x0008 sqn: 0x00000e9b srt: 0 sta: 9 flg: 0x2 ktucf redo: uba: 0x00c0193e.02b8.03 ext: 3 spc: 7624 fbi: 0

非IMU模式下DML语句产生的REDO日志内容格式解读

这个话题讨论在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 file
5.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:0x010000fd OBJ:22327 SCN:0x0000.00719188 SEQ:1 OP: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:4294967295 SCN: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”

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

ORACLE临时表介绍:
ORACLE数据库除了可以保存永久表外,还可以建立临时表temporary tables。这些临时表用来保存一个会话SESSION的数据,或者保存在一个事务中需要的数据。当会话退出或者用户提交commit和回滚rollback事务的时候,临时表的数据自动清空,但是临时表的结构以及元数据还存储在用户的数据字典中。

Oracle临时表分为 会话级临时表 和 事务级临时表。
会话级临时表是指临时表中的数据只在会话生命周期之中存在,当用户退出会话结束的时候,Oracle自动清除临时表中数据。
事务级临时表是指临时表中的数据只在事务生命周期中存在。当一个事务结束(commit or rollback),Oracle自动清除临时表中数据。
临时表中的数据只对当前Session有效,每个Session都有自己的临时数据,并且不能访问其它Session的临时表中的数据。因此,临时表不需要DML锁。

当一个会话结束(用户正常退出 用户不正常退出 ORACLE实例崩溃)或者一个事务结束的时候,Oracle对这个会话的表执行 TRUNCATE 语句清空临时表数据.但不会清空其它会话临时表中的数据.可以索引临时表和在临时表基础上建立视图.同样,建立在临时表上的索引也是临时的,也是只对当前会话或者事务有效. 临时表可以拥有触发器.

全文的REDO/UNOD大小的单位均为BYTES。

一、环境及用户
BYS@bys1>select * from v$version;

BANNER
——————————————————————————–
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 – Production
PL/SQL Release 11.2.0.1.0 – Production
CORE 11.2.0.1.0 Production
TNS for Linux: Version 11.2.0.1.0 – Production
NLSRTL Version 11.2.0.1.0 – Production

BYS@bys1>select force_logging from v$database;

FOR

NO
BYS@bys1>select * from user_role_privs;
USERNAME GRANTED_ROLE ADM DEF OS_
—————————— —————————— — — —
BYS DBA NO YES NO
BYS@bys1>select * from tab;
TNAME TABTYPE CLUSTERID
—————————— ——- ———-
DEPT TABLE
EMP TABLE
SYS_TEMP_FBT TABLE

创建一个表,600W条数据–源数据为dba_objects,通过多次查询插入。

BYS@bys1>create table test9 as select * from dba_objects;
Table created.

BYS@bys1>insert into test9 select * from test9; —多次使用此语句插入数据

BYS@bys1>commit;
Commit complete.
BYS@bys1>select count(*) from test9; 将近700W条。
COUNT(*)
———-
6957120

#########################################

二、创建一个普通表,并统计建表及插入数据等操作所产生的REDO及UNDO大小
注:其中每一步后的查看REDO及UNDO大小我都查询了好几遍,节约篇幅未列出;并且测试系统上只有此客户端在数据库环境中进行操作。

建表前后的REDO/UNDO大小变化
BYS@bys1>select name,value as bytes from (select b.name,a.value from v$mystat a,v$statname b where a.STATISTIC#=b.statistic#) where name=’redo size’ or name like ‘undo change%’;
NAME BYTES
—————————————————————- ———-
redo size 1824
undo change vector size 188

BYS@bys1>create table test1 as select * from test9 where 1=0;
Table created.
BYS@bys1>select name,value as bytes from (select b.name,a.value from v$mystat a,v$statname b where a.STATISTIC#=b.statistic#) where name=’redo size’ or name like ‘undo change%’;

NAME BYTES
—————————————————————- ———-
redo size 238604
undo change vector size 6924

插入数据前后的REDO/UNDO大小变化
BYS@bys1>insert into test1 select * from test9; —需要时间较长,我这里用了8分半。
6957120 rows created.

Elapsed: 00:08:26.37
BYS@bys1>select name,value as bytes from (select b.name,a.value from v$mystat a,v$statname b where a.STATISTIC#=b.statistic#) where name=’redo size’ or name like ‘undo change%’;
NAME BYTES
—————————————————————- ———-
redo size 813924652
undo change vector size 30676180
提交前后的REDO/UNDO大小变化
BYS@bys1>commit;
Commit complete.

Elapsed: 00:00:00.05
BYS@bys1>select name,value as bytes from (select b.name,a.value from v$mystat a,v$statname b where a.STATISTIC#=b.statistic#) where name=’redo size’ or name like ‘undo change%’;
NAME BYTES
—————————————————————- ———-
redo size 813924888
undo change vector size 30676180

查询前后的REDO/UNDO大小变化:
第一次查询产生REDO是因为延迟块清除:
BYS@bys1>set autotrace on
BYS@bys1>select count(*) from test1;
COUNT(*)
———-
6957120
Elapsed: 00:01:38.73
Execution Plan
———————————————————-
Plan hash value: 3896847026

——————————————————————–
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
——————————————————————–
| 0 | SELECT STATEMENT | | 1 | 26827 (1)| 00:05:22 |
| 1 | SORT AGGREGATE | | 1 | | |
| 2 | TABLE ACCESS FULL| TEST1 | 7495K| 26827 (1)| 00:05:22 |
——————————————————————–

Note
—–
– dynamic sampling used for this statement (level=2)

Statistics
———————————————————-
29 recursive calls
1 db block gets
198000 consistent gets
99253 physical reads
5000 redo size
425 bytes sent via SQL*Net to client
419 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
BYS@bys1>set autotrace off
BYS@bys1>select name,value as bytes from (select b.name,a.value from v$mystat a,v$statname b where a.STATISTIC#=b.statistic#) where name=’redo size’ or name like ‘undo change%’;
NAME BYTES
—————————————————————- ———-
redo size 813932848
undo change vector size 30678540

正常查询并没有产生REDO和UNDO
BYS@bys1>select count(*) from test1;

COUNT(*)
———-
6957120

Elapsed: 00:00:26.95
BYS@bys1>select name,value as bytes from (select b.name,a.value from v$mystat a,v$statname b where a.STATISTIC#=b.statistic#) where name=’redo size’ or name like ‘undo change%’;
NAME BYTES
—————————————————————- ———-
redo size 813932848
undo change vector size 30678540

统计情况如下:
create table test1 as select * from dba_objects where 1=0;语句:产生REDO/UNDO分别为: 236780 6736

insert into test1 select * from dba_objects;语句:产生REDO/UNDO分别为: 813686048 30669256
COMMIT语句:产生REDO/UNDO分别为:236和0

三、创建一个ON COMMIT DELETE ROWS 临时表,并统计建表及插入数据等操作所产生的REDO及UNDO大小
PRESERVE ROWS临时表中的测试和ON COMMIT DELETE ROWS结果类似,不再重复贴了。

在上一步做完后退出SQLPLUS再登陆进行操作。

建表前后的REDO/UNDO大小变化
BYS@bys1>select name,value as bytes from (select b.name,a.value from v$mystat a,v$statname b where a.STATISTIC#=b.statistic#) where name=’redo size’ or name like ‘undo change%’;
NAME BYTES
—————————————————————- ———-
redo size 1956
undo change vector size 164
BYS@bys1>create global temporary table temp1 on commit delete rows as select * from test9 where 1=0;
Table created.
BYS@bys1>select name,value as bytes from (select b.name,a.value from v$mystat a,v$statname b where a.STATISTIC#=b.statistic#) where name=’redo size’ or name like ‘undo change%’;
NAME BYTES
—————————————————————- ———-
redo size 26404
undo change vector size 6692

插入数据前后的REDO/UNDO大小变化
BYS@bys1>insert into temp1 select * from test9;
6957120 rows created.
BYS@bys1>select name,value as bytes from (select b.name,a.value from v$mystat a,v$statname b where a.STATISTIC#=b.statistic#) where name=’redo size’ or name like ‘undo change%’;
NAME BYTES
—————————————————————- ———-
redo size 43254212
undo change vector size 30540820
BYS@bys1>select count(*) from temp1;
COUNT(*)
———-
6957120
BYS@bys1>select name,value as bytes from (select b.name,a.value from v$mystat a,v$statname b where a.STATISTIC#=b.statistic#) where name=’redo size’ or name like ‘undo change%’;
NAME BYTES
—————————————————————- ———-
redo size 43254212
undo change vector size 30540820

提交前后的REDO/UNDO大小变化
BYS@bys1>commit;
Commit complete.
BYS@bys1>select name,value as bytes from (select b.name,a.value from v$mystat a,v$statname b where a.STATISTIC#=b.statistic#) where name=’redo size’ or name like ‘undo change%’;
NAME BYTES
—————————————————————- ———-
redo size 43254448
undo change vector size 30540820

查询前后的REDO/UNDO大小变化:–无变化
BYS@bys1>select count(*) from temp1;
COUNT(*)
———-
0
BYS@bys1>select name,value as bytes from (select b.name,a.value from v$mystat a,v$statname b where a.STATISTIC#=b.statistic#) where name=’redo size’ or name like ‘undo change%’;
NAME BYTES
—————————————————————- ———-
redo size 43254448
undo change vector size 30540820
统计情况如下:
create global temporary table temp1语句: 产生REDO和UNDO分别为: 24448 6528

insert into temp1 select * from dba_objects;语句:产生REDO和UNDO分别为:43227808 30534128
COMMIT语句:产生REDO/UNDO分别为: 1346 和0

四:两次操作产生的REDO/UNDO大小对比
普通表统计情况如下:
create table test1 as select * from dba_objects where 1=0;语句:产生REDO/UNDO分别为: 236780 6736

insert into test1 select * from dba_objects;语句:产生REDO/UNDO分别为: 813686048 约775.99M 30669256
COMMIT语句:产生REDO/UNDO分别为:236和0
ON COMMIT DELETE ROWS 临时表统计情况如下:
create global temporary table temp1语句: 产生REDO和UNDO分别为: 24448 6528

insert into temp1 select * from dba_objects;语句:产生REDO和UNDO分别为: 43227808 约41M 30534128
COMMIT语句:产生REDO/UNDO分别为: 1346 和0

总结:临时表的建立和插入数据也产生REDO和UNDO。
建立临时表时因为修改了数据字典所以产生了少量REDO与UNDO;

提交时是在REDO中插入一条提交的标签,所以只产生少量REDO。

那么在插入数据时,临时表还是会产生REDO和UNDO,但是REDO量比普通表插入相同数据量时产生的REDO少很多,UNDO大小相近,这个是怎么解呢?

大致是因为:临时表产生了undo,而undo的变化又产生了REDO LOG, 所以临时表的DML操作也产生了REDO。
但是临时表产生的REDO的大小却比普通表DML操作的小,是因为临时表中不记录表中数据变化所产生的REDO,只记录了UNDO数据变化所产生的REDO。

临时表会产生UNDO,是因为临时表操作和普通表是一样的,也要支持rollback和commit,这样自然要记录到undo中。

普通表与临时表DML操作会产生REDO/UNDO对比与分析

DDL操作产生产生UNDO和REDO。原因是:
delete 需要把每个有数据的数据块读出来,写上delete标记, 另外还要把delete的内容拷一份到undo,还要把它的动作记到redo。
而truncate , 就是在系统表(或者tablespace bitmap)里面,把相关的extent 的 标记未未使用,另外把dba_objects(obj$)里的data_object_id换一下。

1.ddl所产生的undo量视乎其所要维护数据字典的操作类型和操作量.DDL执行失败也产生少量UNDO,因为执行少量递归操作后,Oracle发现所要drop的对象并不存在,将会rollback之前的”部分”递归dml操作。
2.DDL操作产生的REDO是因为DDL修改的字典表和一些段头信息产生的redo。

SQL> select name,value as bytes from (select b.name,a.value from v$mystat a,v$statname b where a.STATISTIC#=b.statistic#) where name=’redo size’ or name like ‘undo change%’;
NAME BYTES
—————————————————————- ———-
redo size 5628
undo change vector size 2212
SQL> select * from tab;
TNAME TABTYPE CLUSTERID
—————————— ——- ———-
SYS_TEMP_FBT TABLE
TEST TABLE
TEST1 TABLE
SQL> drop table test;
Table dropped
SQL> select name,value as bytes from (select b.name,a.value from v$mystat a,v$statname b where a.STATISTIC#=b.statistic#) where name=’redo size’ or name like ‘undo change%’;
NAME BYTES
—————————————————————- ———-
redo size 12608
undo change vector size 4216
SQL> select * from cat;

TABLE_NAME TABLE_TYPE
—————————— ———–
BIN$eSjr2ednQKavapT1EPZ/aw==$0 TABLE
SYS_TEMP_FBT TABLE
TEST1 TABLE

SQL> select 12608-5628 as redo_size_drop_change,4216-2212 as undo_size_dorp_change from dual;

REDO_SIZE_DROP_CHANGE UNDO_SIZE_DORP_CHANGE
——————— ———————
6980 2004

DDL操作产生UNDO和REDO的示例

1.一致性读:
假设从9点时发出一条查询,此查询语句运行了一分钟,那么查询的是9点时表内信息,如果在9时至9:00:30之间修改并提交了数据,查询语句扔查询结果仍是9点时的表内的数据。

实验步骤如下:
在SESSION1中发出查询语句(增加条件延长查询语句运行时间)
在SESSION2中修改并提交。(需要在SESSION1查询语句运行期间进行)
SESSION1:
9:26:50 SQL> select * from test;
A
———-
1
2
3
4
5
6
7
16
18
19
10 rows selected

下面这条语句能够执行一分钟左右,在语句执行时,抓紧时间去SESSION2中提交修改的数据。

可以看到,查询出的是发出查询时表内的数据:

9:27:26 SQL> select * from test where a=7 and (select count(*) from dba_objects,dba_tables)>1 and (select count(*) from dba_objects,dba_tables)>2 ;
A
———-
7
9:28:05 SQL>

SESSION2:
9:27:13 SQL> select * from test;
A
———-
1
2
3
4
5
6
7
16
18
19
10 rows selected
9:27:14 SQL> update test set a=a+7 where a=7;
1 row updated
9:27:54 SQL> commit;
Commit complete
9:27:57 SQL> SELECT * FROM TEST
A
———-
1
2
3
4
5
6
14
16
18
19
10 rows selected
9:28:50 SQL>

2.current read:
读取当前的 data block,最新的 data block,比如在update, delete的时候就总是current read。
因为要对最新的data block做更改,对过去更改没有实际意义。
执行过程描述:
session 1 开始了一个update 操作,通过consistent read(a=9) 获取了 数据块的id。使用WHERE后语句使得这个UPDATE操作需要持续很长时间。
session 2 在SESSION1的UPDATE未执行时,修改了 a=9 这一行的数据,变成了a=18
session 1 通过一个通过最开始查询a=9拿到的block id去以current read读取数据块,结果发现数据块不符合filter的条件a=9。所以 session 1没有更新。

session 1:
SQL> set time on
9:06:43 SQL> select a,DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID) from test;
A DBMS_ROWID.ROWID_BLOCK_NUMBER(
———- ——————————
1 242
2 242
3 242
4 242
5 242
6 242
7 242
8 242
9 242
10 242
10 rows selected

在SESSION1执行以下语句,因为执行时间较长,大约要一分钟,在执行期间去SESSION2提交更改的数据。
9:10:15 SQL> update test set a=a+1 where a=9 and (select count(*) from dba_objects,dba_tables)>1;
0 rows updated
9:10:40 SQL>
9:14:04 SQL> select * from test;
A
———-
1
2
3
4
5
6
7
8
18
10
10 rows selected
9:14:10 SQL>

SESSION2:
SQL> set time on
9:07:48 SQL> update test set a=a+9 where a=9;
1 row updated
9:10:34 SQL> commit;
Commit complete
9:10:37 SQL>

一致性读和current read演示