关于数据块空间和migrate row的研究

[复制链接]
查看11 | 回复6 | 2005-10-30 17:05:33 | 显示全部楼层 |阅读模式
./vagentd -re AAABiXAAEAAAAA3ADY
Internal Rowid [ 10]: 0000 1897 0100 0037-00D8
使用chainrow分析工具,我们可以轻易的得到这个表中有多少个migrate row。取其中任意一个rowid,转换成内部的格式。Base64的转化方式可以通过很多方式来转换。在这里转换完成后:
0000 1897 0100 0037-00D8
1897转换成10进制为6295
0x0100 0037左移10位右移10位为block号,右移22位为file#
00D8转换成10进制为slot号,slot号即为一个快上的第几个row,下面将提及。
(gdb) p 0x01000037>10
$4 = 55
(gdb) p 0x00D8
$5 = 216
(gdb) p 0x01000075>10
$6 = 117
以上为转换方式,因为我们知道这个行为migrate row了。


tab 0, row 216, @0x7ff
tl: 9 fb: --H----- lb: 0x1cc: 0
nrid:0x01000075.1
很轻易的,我们通过dump datafile block可以得到这个块,并且找到这个slot:216,发现原来存在这里的行,fb: --H-F-L---不见了,得到的只是一个H。接下来是一个nrid,nrid就是下一个块的连接。
nrid:0x01000075.1
我们知道了这个块是117个属于file#=4,同时.1表示了row 1,所以我们直接dump到117块,得到下面的结果。
tab 0, row 1, @0x1eb8
tl: 52 fb: ----FL-- lb: 0x1cc: 3
hrid: 0x01000037.d8
col0: [ 3]c2 5a 61
col1: [30]
41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59
5a 31 32 33 34
col2: [ 7]78 81 08 09 0c 15 1e
果然,这个行在这里,而且他还显示了hrid,即header rowid为0x01000037.d8,slot号为216(d8)
看看数据是否正确,呵呵。
在oracle9i中,我们可以再看些有趣的东西。
我用了一个脚本产生了一个新表插入了501行,我们通过seg_header中的first level block可以看到,这里(红色部分)只有一个块是满的full,其他的都是75%~100%空的,我们dump这个块发现她里面有nrow=339,应该还有162行,在第15块里。因为6:50-75% free显示了这个玄机。而去dump 第15块(可以通过rowid找到)果然是的,nrow162。
Extent Map Block Offset: 4294967295
First free datablock : 4
Bitmap block lock opcode 0
Locker xid: :0x0000.000.00000000
Highwater::0x01000011ext#: 0blk#: 8ext size: 8
#blocks in seg. hdr's freelists: 0
#blocks below: 5
mapblk0x00000000offset: 0
HWM Flag: HWM Set
--------------------------------------------------------
DBA Ranges :
--------------------------------------------------------
0x01000009Length: 8Offset: 0
0:Metadata 1:Metadata 2:Metadata 3:FULL
4:75-100% free 5:75-100% free 6:50-75% free 7:75-100% free
--------------------------------------------------------
End dump data blocks tsn: 4 file#: 4 minblk 9 maxblk 9
这是update这个表将其中一个字段扩展到30个字符,发现产生了339个migrate row,而在第12块中(即刚才的full状态)只产生了238个,然后dump第15个块,发现里面有nrid为101,所以加起来为339个migrate rows。
那么我们可以得出第一个结论,oracle对于full的块的更新肯定将产生row migrate(其实也不太肯定,只是几次的结果都一样,所以没有办法了),full块上的row迁移到下一个和他相关联的块上,如果这个块有空间的话。如下面所示:
tab 0, row 162, @0xb78
tl: 57 fb: ----FL-- lb: 0x1cc: 3
hrid: 0x0100000c.18
这是从15块上得到的第一个hrid,刚好了12块上产生第一个的migrate row。而这个块上有44个hrid,即12上至少有44个row迁移到此。这里我们也能推算一下,oracle更新的时候是从extent头的块开始的。因为12块有的块迁移了,留下的只是nrid一个指针。因此12块就应该有一些空间了,结果是对的,oracle很机灵的留下了原始的一部分行没有动,而是从这个块的尾巴向前推进。

SQL> update test01 set f2='ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890';
501 rows updated.
SQL> commit;
Commit complete.
SQL> conn /as sysdba
Connected.
SQL> truncate table chained_rows;
Table truncated.
SQL> analyze table dsg.test01 list chained rows;
Table analyzed.
SQL> select count(*) from chained_rows;
COUNT(*)
----------
339
SQL> alter system dump datafile 4 block 9;
System altered.
SQL> exit
Extent Map Block Offset: 4294967295
First free datablock : 8
Bitmap block lock opcode 0
Locker xid: :0x0000.000.00000000
Highwater::0x01000019ext#: 1blk#: 8ext size: 8
#blocks in seg. hdr's freelists: 0
#blocks below: 13
mapblk0x00000000offset: 1
HWM Flag: HWM Set
--------------------------------------------------------
DBA Ranges :
--------------------------------------------------------
0x01000009Length: 8Offset: 0
0x01000011Length: 8Offset: 8
0:Metadata 1:Metadata 2:Metadata 3:FULL
4:FULL 5:FULL 6:FULL 7:FULL
8:75-100% free 9:75-100% free 10:50-75% free 11:75-100% free
12:75-100% free 13:75-100% free 14:75-100% free 15:75-100% free
--------------------------------------------------------
End dump data blocks tsn: 4 file#: 4 minblk 9 maxblk 9
这样看来因为在15块上有44个hrid,说明有44个行从12迁移过来,同时有101个nrid,说明有101个行迁走了,原因是15这个块是最后被更新的,因为oracle发现来更新这个块的时候,该块也已经是full了,就只有将这个块上的某些行迁移走了。我们看到的最后结果是4号5号块也满了,7号也满了。同时oracle扩展了这个extent中的另外的8个块。并且格式化了。我在这里看到的和eygle看到好像不同,oracle是8个块8个块开始格式的,因为first level block管理了16个块,所以格式是以extent为单位的,当然到超过16个extent后,因为first level block管理的64个块,所以格式可能是16一格吧。
Oracle的这种迁移方式,减少了碎片的产生。当然chained row没有这么复杂了,相比起来migrate row动作大些,chained row不移动行的位置,而是扩块。
现在我有几个问题没有弄明白:
1.
为什么首次插入的时候,oracle使用的块是12块和15块,这个两个块的关系怎么知道的?
2.
在second level block 中纪录的0x01000009Free: 5 Inst: 1,指的是这个first level block管理的块中还有空间,但是0x01000009Free: 3 Inst: 1,0x01000009Free: 2 Inst: 1,都可能产生,oracle怎么来估算free的值是2/3/5呢?
附脚本:
sqlplus dsg/dsgdesc test01
Name
Null?Type
----------------------------------------- -------- ----------------------------
F1
NUMBER
F2
VARCHAR2(90)
F3
DATE
回复

使用道具 举报

千问 | 2005-10-30 17:05:33 | 显示全部楼层
oracle对于full的块的更新肯定将产生row migrate???要看你的pctfree设置的多少 ASSM 情况不同
oracle怎么来估算free的值是2/3/5呢? oracle的每个block中应该都有记数标示这个block中占用了多少的空间剩余的空间
ASSM中对这个segment的研究我看的不是很多多试验一下可以看出来的
关于block的格式 给你个参考:http://l2g32003.home4u.china.com/block/table_block.html
回复

使用道具 举报

千问 | 2005-10-30 17:05:33 | 显示全部楼层
呵呵,这个链接早就看过了
0:Metadata 1:Metadata 2:Metadata 3:FULL
4:75-100% free 5:75-100% free 6:50-75% free 7:75-100% free
表示了这个各个块的使用情况。
我的意思是说在seg header中,first level如何选择存储。同时在second level中,如果表示的free 2/3/5 这些等级呢?
回复

使用道具 举报

千问 | 2005-10-30 17:05:33 | 显示全部楼层
谈谈我的理解
1.这个应该没有什么必然的关系吧,free list中刚好就取到了12和15块
2.可否再说清楚一点,没看出和上面的联系
关于row migration这个同意二楼的意见,因为插入的时候并不会占用PCTFREE的部分,当更新数据在PCTFREE空间内的时候不会产生行迁移,当PCTFREE空间占满了再进行更新动作时就会产生行迁移了
回复

使用道具 举报

千问 | 2005-10-30 17:05:33 | 显示全部楼层
“Oracle的这种迁移方式,减少了碎片的产生。当然chained row没有这么复杂了,相比起来migrate row动作大些,chained row不移动行的位置,而是扩块。“
楼主可否再详细解释一下这句话
”oracle的这种迁移方式“是指哪种?
”减少碎片的产生“是指什么?
chain row和migrationrow的触发条件是不一样的啊,从广义上来讲,migration row可以算是chain row的一种特例
”扩块“是楼主通俗的解释吗,因为chain row内部实现还是通过每个data block中定义指针指向前一个block和后一个block这样"chain"起来的
回复

使用道具 举报

千问 | 2005-10-30 17:05:33 | 显示全部楼层
最初由 eagle_fan 发布
[B]“Oracle的这种迁移方式,减少了碎片的产生。当然chained row没有这么复杂了,相比起来migrate row动作大些,chained row不移动行的位置,而是扩块。“
楼主可否再详细解释一下这句话
”oracle的这种迁移方式“是指哪种?
”减少碎片的产生“是指什么?
chain row和migrationrow的触发条件是不一样的啊,从广义上来讲,migration row可以算是chain row的一种特例
”扩块“是楼主通俗的解释吗,因为chain row内部实现还是通过每个data block中定义指针指向前一个block和后一个block这样"chain"起来的 [/B]

你说的是对的,我这里讲的扩块是说,chain row一般在首次插入的时候产生,一般跨两个块以上,数据是分在两个块或者以上的。
而migrate row一般是一个块上,只是在原来的地方有一个nrid的指针,原来的块上不会有该行数据了。
我指的减少碎片就是说,假如一个一个表有501行,他存放在12块和15块上,12块是full(339行),15块为75%~100%,如果更新整个表的话,并不是12块上的339行全部产生了migrate row,而在12块上产生了238个,他迁移走的空间供给了剩下来的101个行的更新,然后的在15块上产生的migrate row 为101个可能刚好是个巧合,只是在更新15块上剩下的501-339=162个块的时候计算后产生了101个迁移。因此我们看到的就是,12/15/13/14/17都成了full,没有了空间。如果再更新这个表,还会在12/15/13/14/17上产生migrate row,这样就是无穷无尽了,这里是个猜想,还没有时间来验证一下。
回复

使用道具 举报

千问 | 2005-10-30 17:05:33 | 显示全部楼层
如果是 行迁移了,剩下来的空间当然可以被剩下的 行 长度增加所用。
因为oracle根本不会识别空间是如何剩下来的,在block内部记录了 总空间大小和 已被使用空间大小 ,oracle只根据这两者来评估是否能插入新的记录或者 是否产生行迁移。
如果block内部可用空间是不连续的,并且连续空间无法容纳 长度将增加的这条记录,但是从总体上来看 总空用空间大小是足够的,这个时候oracle会重整这个block内部的存储(都压缩到底部),使得可用空间都连续地未于block上方。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

主题

0

回帖

4882万

积分

论坛元老

Rank: 8Rank: 8

积分
48824836
热门排行