首页 > 数据库 > Oracle > 深入浅出undo记载01
初看eygle的深入浅出的关于回滚段undo,其实刚开始自认为对undo的理解还算清晰,undo的记录的信息,dml时undo如何和buffer cache联系(回滚段也是属于buffer cache),从AUM的管理,flashback利用undo来闪回,undo表空间的回滚段的自动扩展于回收,切换undo表空间,快速块清除,延迟块清除,回滚段过旧等,看了回滚这一章发现自己还是有颇多的理解误区和盲区。
回滚段具体记录的是什么:
在看冯春培的回滚段探究中提到了回滚段具体记载的是什么,同样eygle深入浅出中再次提到了回滚段的具体记录的是什么,自己也有误区认为回滚段会记录整个数据块的前景象,那样对空间消耗可是很大的。
对于dml操作,回滚段做以下分类记载:
1 insert 操作回滚段记录的插入数据的rowid,回滚时删除rowid上的数据
2 update操作回滚段记录的更新数据的字段的旧值,回滚时利用回滚段中的旧值重写block中的数据
3 delete操作回滚段记录整行数据的旧值,回滚时在从数据从回滚段反向插入到block中去
分批提交处理dml事物:
对于相同数据量的操作,insert产生的undo最少,update其次,delete产生的最多,这也就是经常文档中建议对于dml操作时,特别是delete操作时,分批处理提交,减少对回滚段的占用和冲击,不然很有可能会出现所谓的ora-01555回滚段过旧而让一个执行半天的事物出现错误而回滚。
在oracle 9I前,回滚表空间都需要手工维护管理,事物使用的回滚段可以如下设置:
Alter rollback segment undo_seg01 online;
Set transaction use rollback segment undo_seg01;
整个事物期间使用undo_seg01回滚段,当然回滚段必须存在且上线,可以查询v$rollstat,dba_rollback_segs视图信息。
当然在undo_management=manual手工管理undo表空间时,也可以手工create回滚段。
Create rollback segment undo_seg02 tablespace untbso01;
Oracle9I后,AUM的出现,自动管理回滚段的出现已经不需要也不能手工去创建回滚段和制定事物使用回滚段等,回滚段的动态创建 上线 扩展 回缩 下线和回收都由oracle自动管理,可以在alert警告日志中查看相应信息,Aum管理下,数据库初始创建10个回滚段和1个系统回滚段。
SQL> update test03 set id=12 where id=11;
1 row updated
SQL> select xidusn,xidslot,xidsqn,ubafil,ubablk,ubarec from v$transaction;
XIDUSN XIDSLOT XIDSQN UBAFIL UBABLK UBAREC
---------- ---------- ---------- ---------- ---------- ----------
9 22 582 2 2250 39
SQL> select usn,extents,rssize,writes,xacts,hwmsize,shrinks from v$rollstat where usn=9;
USN EXTENTS RSSIZE WRITES XACTS HWMSIZE SHRINKS
---------- ---------- ---------- ---------- ---------- ---------- ----------
9 3 1171456 73306 1 1171456 0
V$rollstat视图中字段xacts字段代表的是该回滚段活动事务的数量。
SQL> select usn,name from v$rollname where usn=9;
USN NAME
---------- ------------------------------
9 _SYSSMU9$
此时update语句没有提交,在另一个session下dump回滚段信息。
Dump回滚段_SYSSMU9$段头信息
Sql> alter system dump undo header '_SYSSMU9$';
Sql> select a.value||''||b.instance||'_ora_'||c.spid trace_name from
(select value from v$parameter where name='user_dump_dest')a,
(select instance from v$thread) b,
(select spid from v$process a,v$session b,v$mystat c where b.sid=c.sid and b.paddr=a.addr and c.statistic#=1)c
查看回滚段_SYSSMU9$。
Undo Segment: _SYSSMU9$ (9)
********************************************************************************
Extent Control Header
-----------------------------------------------------------------
Extent Header:: spare1: 0 spare2: 0 #extents: 3 #blocks: 143
last map 0x00000000 #maps: 0 offset: 4080
Highwater:: 0x008008ca ext#: 2 blk#: 65 ext size: 128
#blocks in seg. hdr's freelists: 0
#blocks below: 0
mapblk 0x00000000 offset: 2
index state cflags wrap# uel scn dba parent-xid nub stmt_num cmt
------------------------------------------------------------------------------------------------
0x00 9 0x00 0x0246 0x0001 0x0000.001ad5c0 0x008008c8 0x0000.000.00000000 0x00000001 0x00000000 1324601316
0x01 9 0x00 0x0246 0x0007 0x0000.001ad5ca 0x008008c8 0x0000.000.00000000 0x00000001 0x00000000 1324601316
0x02 9 0x00 0x0246 0x0006 0x0000.001ad5e0 0x008008c8 0x0000.000.00000000 0x00000001 0x00000000 1324601316
0x03 9 0x00 0x0246 0x001e 0x0000.001ad6fd 0x008008c9 0x0000.000.00000000 0x00000001 0x00000000 1324601316
。。。。。。
0x15 9 0x00 0x0246 0x0013 0x0000.001ad69f 0x008008c9 0x0000.000.00000000 0x00000001 0x00000000 1324601316
0x16 10 0x80 0x0246 0x0002 0x0000.00000000 0x008008ca 0x0000.000.00000000 0x00000001 0x00000000 0
0x17 9 0x00 0x0246 0x000c 0x0000.001ad6d8 0x008008c9 0x0000.000.00000000 0x00000001 0x00000000 1324601316
可以看出在0x16转换为10进制也就是22,也就是第22号事务槽,state为10代表是活动事务。回滚段头事务表中的Dba(data block address)指向的是包含这个事务的前镜像. 0x008008ca经转换也就是file 2 block 2250
将回滚段中这个block dump出来
Sql>Alter system dump datafile 2 block 2250;
部分dump文件信息:
其中的irb指的是回滚段中记录的最近未提交变更开始之处,如果开始回滚,irb是起始的搜索点。
UNDO BLK:
xid: 0x0009.016.00000246 seq: 0xda cnt: 0x29 irb: 0x29 icl: 0x0 flg: 0x0000
接下来是回滚段信息的偏移量,最后一个偏移地址正是irb 0x29的信息
Rec Offset Rec Offset Rec Offset Rec Offset Rec Offset
---------------------------------------------------------------------------
0x01 0x1f68 0x02 0x1ee0 0x03 0x1e60 0x04 0x1ddc 0x05 0x1d5c
0x06 0x1cd8 0x07 0x1c58 0x08 0x1bd0 0x09 0x1b50 0x0a 0x1ac8
0x0b 0x1a48 0x0c 0x19c0 0x0d 0x1940 0x0e 0x18b8 0x0f 0x1838
0x10 0x17b0 0x11 0x1730 0x12 0x16a8 0x13 0x1628 0x14 0x1588
0x15 0x1508 0x16 0x1470 0x17 0x1420 0x18 0x13a0 0x19 0x131c
0x1a 0x12b4 0x1b 0x1234 0x1c 0x119c 0x1d 0x111c 0x1e 0x1094
0x1f 0x1014 0x20 0x0f7c 0x21 0x0efc 0x22 0x0e74 0x23 0x0e24
0x24 0x0d88 0x25 0x0d48 0x26 0x0ca0 0x27 0x0c08 0x28 0x0b98
0x29 0x0b28
。。。。。。
然后继续在dump文件中找到0x29信息,c1 22也就是最后更新记录的前镜像,rci代表的是undo chain(同一事务的多次修改,根据chain链接关联)的下一个偏移量,这样继续用chain链接关联,undo chain的指针为0x00,表示这个事务内最后更新一条记录。oracle就这样通过回滚段保留前镜像(不过这个数字如何转换自己还不清楚)
*-----------------------------
* Rec #0x29 slt: 0x16 objn: 51375(0x0000c8af) objd: 51375 tblspc: 4(0x00000004)
* Layer: 11 (Row) opc: 1 rci 0x28
Undo type: Regular undo Last buffer split: No
Temp Object: No
Tablespace Undo: No
rdba: 0x00000000
*-----------------------------
KDO undo record:
KTB Redo
op: 0x02 ver: 0x01
op: C uba: 0x008008ca.00da.28
Array Update of 1 rows:
tabn: 0 slot: 2(0x2) flag: 0x2c lock: 0 ckix: 0
ncol: 1 nnew: 1 size: 0
KDO Op code: 21 row dependencies Disabled
xtype: XAxtype KDO_KDOM2 flags: 0x00000080 bdba: 0x0100005e hdba: 0x0100005b
itli: 2 ispac: 0 maxfr: 4858
vect = 0
col 0: [ 2] c1 22
这里再查看x$bh和dba_extents视图,
SQL> select b.segment_name,a.dbarfil,a.dbablk,a.class,a.state,a.file# from x$bh a,dba_extents b
2 where b.owner='XIAOYU' and b.relative_fno=a.dbarfil and b.block_id<=a.dbablk and b.block_id+b.blocks>a.dbablk
3 and segment_name='TEST03';
SQL> select distinct b.segment_name,a.dbarfil,a.dbablk,a.class,a.state,a.file# from x$bh a,dba_extents b
2 where b.owner='XIAOYU' and b.relative_fno=a.dbarfil and b.block_id<=a.dbablk and b.block_id+b.blocks>a.dbablk
3 and segment_name='TEST03';
SEGMENT_NAME DBARFIL DBABLK CLASS STATE FILE#
-------------------------------------------------------------------------------- ---------- ---------- ---------- ---------- ----------
TEST03 4 94 1 1 4
TEST03 4 96 1 1 4
TEST03 4 95 1 1 4
TEST03 4 94 1 0 4
TEST03 4 91 4 1 4
TEST03 4 92 1 1 4
TEST03 4 93 1 1 4
如果此时在别的session进行查询select * from xiaoyu.test03
SQL> /
SEGMENT_NAME DBARFIL DBABLK CLASS STATE FILE#
-------------------------------------------------------------------------------- ---------- ---------- ---------- ---------- ----------
TEST03 4 94 1 1 4
TEST03 4 96 1 1 4
TEST03 4 95 1 1 4
TEST03 4 94 1 0 4
TEST03 4 91 4 1 4
TEST03 4 92 1 1 4
TEST03 4 94 1 3 4
TEST03 4 93 1 1 4
此时v$bh中会多出一个state=3的块,也就是为了满足一致性读而通过undo和block的构造的数据块的前镜像cr块,此时buffer cache中有file 4 block 94的三个块,其中的state分别为0,1,3,
class 4表示的是段头,class 1表示的实际存储数据信息的数据块。
在前镜像信息中,oracle还记录了前镜像对应的数据块地址,也可以从bdba: 0x0100005e,经转换也就是file 4 block 94,再转换该block
Alter system dump datafile 4 block 94
部分trace文件信息:
Start dump data blocks tsn: 4 file#: 4 minblk 94 maxblk 94
buffer tsn: 4 rdba: 0x0100005e (4/94)
scn: 0x0000.001aeaa2 seq: 0x01 flg: 0x04 tail: 0xeaa20601
frmt: 0x02 chkval: 0x927d type: 0x06=trans data
Hex dump of block: st=0, typ_found=1
Dump of memory from 0x0A5D2200 to 0x0A5D4200
A5D2200 0000A206 0100005E 001AEAA2 04010000 [....^...........]
A5D2210 0000927D 00000001 0000C8AF 001AEAA2 [}...............]
。。。
Itl Xid Uba Flag Lck Scn/Fsc
0x01 0x0008.021.00000221 0x0080042b.00ed.07 C--- 0 scn 0x0000.001a54e5
0x02 0x0009.016.00000246 0x008008ca.00da.29 ---- 3 fsc 0x0000.00000000
这里存在ITL事务槽信息:Xid—transaction ID Uba—Undo block address lck—lck status
Xid进一步分析为:usn=9的回滚段 事务槽22号,wrap#为246正是dump回滚段头中的看到的那个事务的wrap# 0x0246 ,数据块上同样存在指向回滚段的事务信息。
Uba分解:0x008008ca是前镜像的dba,.00da是UNDO BLK的seq顺序号,29是undo记录的开始地址(irb),回滚将从undo blk的irb开始rollback。
可以简约总结下:
1 事务开始时,需要在回滚段事务表上分配一个事务槽
2 在数据块头部获取ITL事务槽,该事务槽指向回滚段头事务槽
3 在修改数据之前,记录前镜像信息,这个信息以undo record的形式存储在回滚段中,回滚段头事务槽指向该记录
4 锁定修改行,修改行锁定为指向ITL事务槽
5 数据修改进行.
以上就是事务的基本流程。
[@more@]来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/25362835/viewspace-1056927/ ,如需转载,请注明出处,否则将追究法律责任。