|
2楼和3楼是2个block的dump信息,大家不要吓着,其实能用到的dump信息很少,不过为了方便一些人阅读还是都放上来了
--其实主要介绍了undo中的2条单向链表,明白了这2条链,有助于我们更深入的研究undo...
欢迎拍砖
--创建一个测试表tt,注意按照object_id事先排序了
SQL> create table tt tablespace users as select * from dba_objects order by obje
ct_id;
表已创建。
--查询一下object_id的最大值和最小值后面分析会用到
SQL> select min(object_id),max(object_id) from tt;
MIN(OBJECT_ID) MAX(OBJECT_ID)
-------------- --------------
2 10327
SQL> update tt set object_id=1;
已更新9882行。
--查看事务使用undo的情况
SQL> select xidusn,xidslot,ubablk,ubarec,start_ubablk,start_ubarec,used_ublk,use
d_urec from v$transaction;
XIDUSN XIDSLOT UBABLK UBAREC START_UBABLK START_UBAREC USED_UBLK USED_UREC
------ ------- ------ ------ ------------ ------------ ---------- ----------
4 26 747 49 37 7 190 19671
SQL>
update操作开启的这个事务共使用了190个block(上面查询USED_UBLK字段),那么这190个block其实
是一个由ubablk=747指向start_ubablk=37的单向链表,详细了解可以参考我之前写过的一篇文章:
http://www.itpub.net/viewthread. ... e%3D1&frombbs=1
在v$transaction中字段UBABLK排在START_UBABLK的前面是有一定道理的,因为UBABLK相对而言其实比
START_UBABLK更加有用,或者说UBABLK比START_UBABLK在事务恢复时要更早的用到,因为在事务恢复时是
倒着恢复的或者叫逆向恢复的,什么是逆向恢复呢?简单的说就是最后被修改的记录在恢复时先被恢复,
oracle之所以这样做我想无非是为了保证事务能够被完全或者被彻底恢复,因为最后一条记录的before image
在undo中都产生了,那么被修改的第一条记录的before image肯定产生了,也就是说这个事务被完成了,
这样表述不知道是否准确。
接下来我们还是先看看这190个block的分布情况,目的是使一会的dump更加清楚:
首先看看我们的事务使用了哪个undo segment:
SQL> select usn,xacts from v$rollstat where xacts<>0;
USN XACTS
---------- ----------
4 1
SQL> select segment_name,segment_id from dba_rollback_segs where segment_id=4;
SEGMENT_NAME SEGMENT_ID
-------------------- ----------
_SYSSMU4$ 4
SQL> select extent_id,file_id,block_id,blocks from dba_extents where segment_nam
e='_SYSSMU4$';
EXTENT_ID FILE_ID BLOCK_ID BLOCKS
---------- ---------- ---------- ----------
0 2 57 8
1 2 129 8
2 2 225 8
3 2 33 8
4 2 169 8
5 2 217 8
6 2 241 8
7 2 273 8
8 2 345 8
9 2 369 8
10 2 377 8
EXTENT_ID FILE_ID BLOCK_ID BLOCKS
---------- ---------- ---------- ----------
11 2 393 8
12 2 417 8
13 2 433 8
14 2 449 8
15 2 457 8
16 2 649 128
已选择17行。
dump一下事务使用的undo block组成的这个单向链表的第一个block:747
SQL> alter system dump datafile 2 block 747;
系统已更改。
--dump信息在下面
在分析事务恢复的过程之前先来简单介绍一下undo block中的几个要点:
1、undo中其实也是按照记录来存储的,表中的每一条记录被修改之后的
befroe image在undo中其实对应的也是一条记录,每一条记录的表示或者说标号是Rec,
就我们dump的这个block747中一共有 cnt: 0x31=49(10进制数)条记录;
2、最后一条记录是irb: 0x31=49,每一个被事务使用的undo block上为什么要记录irb,
因为irb是事务恢复的起点,irb表示的是什么意思呢?
irb :- Index of first record we need to consider in case of a rollback(active transaction record id)
通过上面的解释我想irb解释成每一个undo block中事务rollback时的起点,i我想应该是undo block中
第一条记录的index,rb是rollback吧,在没有看到e文解释之前,尽管网上有很多解释,但大都解释为:
"irb: 0x5f 指回滚段中记录的最近的未提交变更的开始之处,及最后一次更改之处"我看了这个解释之后
不能理解irb的意思,不知道大家以前是如何理解irb的?
3、知道一个事务使用的undo block组成了一个单向链表,也知道了事务恢复的起点是这个单向链表中最后一个
被使用的block(我们这个事务是block 747)中记录的最后一个rec:我们这个例子是747中的irb: 0x31,为了能够顺利
恢复我们还需要知道每一个undo block中记录(rec)的恢复顺序,其实上面提到逆向恢复了,这里起点是irb: 0x31,下一个
要恢复的当然是irb: 0x30了,这就需要在记录irb: 0x31中确切的知道irb: 0x30的位置,事实上记录irb: 0x31中也确实记录了
irb: 0x30,只不过是通过rci 0x30来表示的,rci是什么意思呢?
rci indicates the next undo record to apply within the undo chain.
这里的rc我想应该是record的意思,i同样是index的意思吧,rci合起来表述的意思应该是record index,不知道猜测的是否准确,
之前网上我看到的很多信息是
:"rci,该参数代表的是undo chain(同一事务的多次修改,根据chain连接关联)的下一个偏移量",看了之后不能很好的理解。
4、现在我们知道了2条链表,一条是事务使用的block组成的链表,另一条是undo block内部通过rci由下向上指向的一条链,通过这2条链我想
oracle可以保证事务顺利的rollback掉。
5、再来简单的分析一下这2条链,block747中的第一条要恢复的记录是Rec #0x31,
而Rec #0x31中记录的被修改的数据的before image是:
col 3: [ 4] c3 02 04 1c
接下来我们看看tt表中最后一条记录(max(object_id)=10327,最开始时我显示出来过)的dump信息:
SQL> select dump(2,16) dump2,dump(10327,16) dump10327 from dual;
DUMP2 DUMP10327
----------------- ----------------------
Typ=2 Len=2: c1,3 Typ=2 Len=4: c3,2,4,1c
SQL>
很显然一致,747中最后一条记录的是tt表中最后一条记录被修改(object_id)时的before
image:10327;Rec #0x31被恢复之后,通过Rec #0x31中记录的rci 0x30找到Rec #0x30恢复,Rec #0x30又找到
Rec #0x2f...如此下去直到找到block 747中的Rec #0x1,那么这个block 747就被使用完了,使用完之后
如何能找到block 746呢,这就用到了另外一条链,也就是需要知道747所指向的下一个undo block,而这个block是通过
记录在Rec #0x1中的rdba: 0x008002ea来实现的:
SQL> select dbms_utility.data_block_address_block(to_number('008002ea','xxxxxxxx
')) next_undo_block from dual;
NEXT_UNDO_BLOCK
---------------
746
SQL>
很显然顺利的找到了,如此下去...直到找到这个事务使用的第一个undo block=37(START_UBABLK)中的第7(START_UBAREC)条记录
Rec #0x7,而Rec #0x7里面记录的rci的值是0x00表示到了这条链的结尾了。
If rci is 0x00 that indicates end of the undo chain within the undo block.
那么block 37的第7条记录是我们tt表中被修改的第一条记录的值2吗?
对比一下看看吧:
Rec #0x7中记录的值是col 3: [ 2] c1 03
SQL> select dump(2,16) from dual;
DUMP(2,16)
-----------------
Typ=2 Len=2: c1,3
SQL>
很显然一致。
[ 本帖最后由 warehouse 于 2010-9-15 11:42 编辑 ] |
|