您的位置:首页 > 其它

关于undo机制的总结[收集中]

2013-09-03 17:29 204 查看
摘要:

事务表是在undo段的段头块上的,[b]事务表里每个数据行记录事务的事务编号XID及该事务对应的用于保存[b]该[b]事务所要修改的表的数据行的原先值的undo块(该[b][b]undo块[/b][/b]当然是位于该事务表所在的undo段里)的地址等,[b][b][b]事务所要修改的表里的数据块的块头(层)上有事务槽,用于存放要修改本数据块的事务的的事务编号XID等信息,当然事务槽上的事务若已经提交了,那么这个事务槽就可以被其他事务使用了(即覆盖)。[/b][/b][/b][/b][/b][/b]

[b][b][b][/b][/b]

[/b]

一、undo记录的rowid信息和各DML操作产生的undo记录大小比较

1、update:在Undo中记录被更新列的前镜像和被更新行ROWID;

2、delete:在Undo中记录被删除行所有列的前镜像和其ROWID;

3、insert:在Undo中记录插入行的ROWID。

所以,按对应产生的undo记录所占空间的大小从小到大排列依次是insert(只记录rowid),update,delete。

这里,有一点要说明的是在UNDO中记录的例如Insert操作对应的插入行的ROWID并非是直接记录的,而是要拼凑出来的。

以下,以Insert操作为例子看看其对应产生的undo记录如何拼凑出rowid信息:

SQL>createtabletest(anumber,bvarchar2(10));

Tablecreated.

SQL>insertintotestvalues(1,'a');

1rowcreated.

SQL>insertintotestvalues(2,'b');

1rowcreated.



下面Rec为0x8的undo记录就是对应于insertinto
testvalues(2,'b');语句产生的

*-----------------------------*
Rec#0x8slt:0x18objn:6469(0x00001945)objd:6469tblspc:0(0x00000000)*
Layer:11(Row)opc:1rci0x07
Undotype:RegularundoLastbuffersplit:No
TempObject:No
TablespaceUndo:No
rdba:0x00000000
*-----------------------------
KDOundorecord:
KTBRedo
op:0x02ver:0x01
op:Cuba:0x0200002e.08ab.07
KDOOpcode:DRProwdependenciesDisabled
xtype:XAbdba:0x00403bdehdba:0x00403bdd
itli:1ispac:0maxfr:4863
tabn:0slot:2(0x2)
没发现ROWID的影子,看来是要通过一些字段拼凑起来了:

[b]“objd:6469”
对应ROWID中的DATA_OBJECT_ID#

“bdba:0x00403bde”对应ROWID中的rfile#,block#

“slot:2(0×2)”对应ROWID中的ROW#[/b]

二、段头块里的事务表的解读

TRC内容,部分内容略掉
indexstatecflagswrap#uelscndbaparent-xidnubstmt_numcmt
------------------------------------------------------------------------------------------------
0x0090x000x02df0x000b0x0000.003f44090x00c00c650x0000.000.000000000x000000010x000000001354068343
0x0190x000x02e20x00000x0000.003f43ff0x00c00c650x0000.000.000000000x000000010x000000001354068343
0x0290x000x02e10xffff0x0000.003f4de10x00c00c610x0000.000.000000000x000000010x000000001354074347
0x03100x800x02e20x00020x0000.003f4e6f0x00c00c610x0000.000.000000000x000000010x000000000
0x0490x000x02e20x000c0x0000.003f45920x00c00c650x0000.000.000000000x000000010x000000001354069244
--索引(index),即事务表上槽号为0x03的行,state为10,cflags为0x80,表示此行是活动(active)事务。
state为9,表示事务是非活动的(可能为expired或unexpired吧)
--wrap#为0x02e2,等于v$transaction里的XIDSQL值,也就是回滚槽被重用了738次。
--uel为0x0002,表示事务当前区,和v$rollstat查到的CUREXT(当前区编号)一致。
--scn为0x0000.003f4e6f,转换为十进制是4148847,和v$transaction的START_SCNB()值相符。
--dba为0x00c00c61,事务对应产生的undo块所在的数据文件编号、块编号
--cmt为0,表示该事务未提交

三、undo块里信息的解读

跟踪文件XXXX.TRC内容,部分内容略

UNDOBLK:

xid:0x0009.003.000002e2seq:0xd1cnt:0x24irb:0x24icl:0x0flg:0x0000


RecOffsetRecOffsetRecOffsetRecOffsetRecOffset

---------------------------------------------------------------------------

0x010x1f900x020x1f280x030x1ee40x040x1e800x050x1e00

0x060x1c580x070x1c040x080x1b440x090x1b000x0a0x1a9c

0x0b0x19d80x0c0x197c0x0d0x121c0x0e0x11d80x0f0x1174

0x100x110c0x110x10a80x120x0f200x130x0edc0x140x0e78

0x150x0e280x160x0d6c0x170x0cbc0x180x0c100x190x0b64

0x1a0x0ab40x1b0x0a080x1c0x093c0x1d0x08900x1e0x07e4

0x1f0x07380x200x06880x210x05e40x220x05580x230x0500

0x240x04a0

--seq:0xd1指的就是v$transaction中的UBASQN字段

--cnt:0x24表示该undo块中有0x24条undo块的undo记录(行)

--irb:0x24,表示回滚链尾端undo记录号为0x24(即REC为0x24的undo记录(行),也即第0x24号undo记录(行))的undo记录,也就是v$transaction中的UBAREC字段

注释:回滚链(undochain)就是指一个事务里的先后产生的多个DML操作对应的undo记录由后指向前组成的(以undo记录里的rci为指针)


根据irb:0x24,查找Rec#0x24

*-----------------------------

*Rec#0x24slt:0x03objn:24633(0x00006039)objd:24633tblspc:6(0x00000006)

*Layer:11(Row)opc:1rci0x23

Undotype:RegularundoLastbuffersplit:No

TempObject:No

TablespaceUndo:No

rdba:0x00000000

*-----------------------------

KDOundorecord:

KTBRedo

op:0x02ver:0x01

compatbit:4(post-11)padding:1

op:Cuba:0x00c00c61.00d1.22

KDOOpcode:URProwdependenciesDisabled

xtype:XAflags:0x00000000bdba:0x020000dehdba:0x020000da

itli:2ispac:0maxfr:4858

tabn:0slot:1(0x1)flag:0x2clock:0ckix:0

ncol:2nnew:1size:4

col1:[6]4f5241434c45

--objn:24633(0x00006039)指的是该undo记录所对应的那个被修改的对象(如表)的逻辑对象号object_id

objd:24633该undo记录所对应的那个被修改的对象(如表)的对象号data_object_id

tblspc:6(0x00000006)指的是该undo记录所对应的那个被修改的对象(如表)所在的表空间号

--hdba:0x020000da指的是该被修改的表所在的段的段头块的地址

bdba:0x020000de指的是该表里具体的那个被修改的数据行所在段里的数据块的地址

--ncol:2指的是该被修改的表有几列

nnew:1指的是该被修改的表的一行实际被修改了几列


--rci0x23,且rdba:0x00000000,表示回滚记录都在此块儿上面(应该说是上回滚记录在此undo块儿上面);如果rdba非0,那就代表回滚链中前一个块所在的位置(或者说如果rdba非0,那rdba值就代表回滚链中前一个undo记录所在的undo块的地址位置)

我们可以根据它的值再dump相关block查看。

--col1:[6]4f5241434c45,就是我做最后一次update的前镜像


附加:
若一个事务产生了五万条undo记录,一个undo块的空间一般是放不下五万条undo记录的,所以这个五万条记录会分布在不同的undo块(这几个undo块不是说要连续放在一起的,随机的)上,那么这个事务对应的事务槽上的uba字段的地址是指向哪个undo记录的呢?
一个DML操作对应会产生一个undo记录,一个包含多个DML操作的事务,其对应的事务槽上的uba字段的地址都是指向该事务里最后一个DML操作所对应的undo记录的地址的(undo块中irb指的就是这个uba地址的第三部分,即REC部分)。无论这个事务对应产生的undo记录是放在一个undo块上,还是多个undo块上,都是这样的。
一个事务对应产生的多个undo记录是如何组织在一起的呢?
就是通过undochain。
回滚链(undochain)就是指一个事务里的先后产生的多个DML操作对应的undo记录由后指向前组成的(以undo记录里的rci为指针将这几个记录连接在一起的)。

如何判断在undochain上的上一个undo记录是否跟本undo记录位于同一个undo块上?

就是通过本undo记录里的rdba来判断的。
rdba:0x00000000,表示回滚记录都在此块儿上面(应该说是上回滚记录在此undo块儿上面);如果rdba非0,那就代表回滚链中前一个块所在的位置(或者说如果rdba非0,那rdba值就代表回滚链中前一个undo记录所在的undo块的地址位置)


四、undo的作用之一事务回滚机制(以下基于推测未试验过)

首先,要说明的是,在一个会话窗口上输入事务回滚命令rollback后所产生的回滚操作只针对该会话下的未提交的事务,对(同一时间)其他会话下的未提交的事务不影响。

undo的另一个作用,即一致性读,也是和会话有关的。例如,表T上一行的name字段值原来为A。现在在会话1下,将之改为B(未提交),接着,还在会话1下,select该行的name字段的值,结果为B。而接下来,在会话2下,select该行的name字段的值,结果为A。所以,undo机制与会话有关的。

会话(内存)上应该记录了会话期间修改了哪些表,(以及这些表最近一次提交时间SCN,)还有在会话里输入rollback命令前的所有(未提交)事务的XID(即事务槽上的XID字段)信息。

这样,当会话里输入rollback命令时,服务器进程就会扫描各个修改过的表的各个数据块上的所有事务槽(当然也包括其他会话里的事务所占的事务槽)的flag是否为提交,若是为未提交(因为块延迟清除机制,这里的未提交不表示真的未提交,还得找事务表上的提交标记),还得根据事务槽上的XID字段找到段头块上的事务表里的对应行,看该行的cmt是否为提交,为提交,就是真的提交,为未提交,就是真的未提交。如果这里为未提交,还要查看该未提交事务所在的事务槽的XID字段是否属于会话里记录过的事务XID,若不是,就跳过该事务(因为该事务属于其他会话的),若是,则就可以根据该未提交事务所在的事务槽的uba字段找到其前镜像,通过该前镜像信息,将当前数据块还原为没开始执行该未提交事务前的状态,这个过程和构造CR块的过程是一样的,只不过构造CR块前先复制一个当前块的副本,在这个副本进行还原。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: