********************************************************
动力小刚原创文章:
时间: 2013-6-27 22:05:14
原文:http://www.itpub.net/thread-1799192-1-1.html
声明:本文是进入itpub门户头条的作品,转载请注明出处
********************************************************
a. 若无特别说明我的测试环境是database10g
b. 大家可按本文先后顺序复制文中代码进程调试
c. 如发现错误欢迎立即提出,方便及时更正
d.文中的“段头L3 BMB”是为了区分”First L3 BMB”临时起的名字
e. 两种bitmap说明:
ASSM段内的bitmap: 用于管理段内的可空间 (本篇)
LMT文件头内的bitmap: 用于管理该数据文件的可用空间(另一篇:http://www.itpub.net/thread-1799520-1-1.html)
***********************************************
第01部分-环境准备:创建表空间z1+创建表段zz1
第02部分-从数据字典查找zz1的段头块
第03部分-从段头L3 BMB查找的L2 BMB
第04部分-从L2 BMB中找出L1 BMB
第05部分-从L1 BMB找可用块
第06部分-补充Insert查找可用块原理
第01部分-环境准备:创建表空间z1+创建表段zz1
01.1-新建Uniform+ASSM的表空间z1
一、表空间的区大小至少5个块
SYS@10G> create tablespace z1 datafile
'/tmp/z1.dbf' size 3M reuse autoextend on next 300K maxsize 999M uniform size 32k;
--ORA-03249: Uniform size for assm tablespace should have atleast 5 blocks
二、段对象的大小比较整齐时用表空间采用统一区大小
SYS@10G> set sqlprompt "_user'@'10G> "
drop tablespace z1 including contents and datafiles cascade constraints;
create tablespace z1 datafile
'/tmp/z1.dbf' size 3M reuse autoextend on next 300K maxsize 999M uniform size 40k;
01.2-建表段zz1并插数据耗用两个区
一、创建表段
SYS@10G>
drop table zz1 purge;
create table zz1 tablespace z1 pctfree 60 as select object_name from dba_objects where rownum=1;
补充:ASSM管理的段只需要PCTFREE一个存储参数
默认是10,为一个块保留的空间百分比是10%,在达到pctfree之前,该block是一直可以被插入的,当数据块的可用空间低于10%后,就不可以被insert了,超过10%部分的空间只能被用于update。
二、插入数据
SYS@10G>
begin
for i in 1..9 loop
insert into zz1 select * from zz1;
end loop;
commit;
end;
/
三、查看区
SYS@10G>
set sqlprompt "_user'@'10G> "
set pagesize 0
set linesize 666
select '--extent#='||extent_id, 'file#='||file_id, 'block#='||block_id from dba_extents where owner='SYS' and segment_name='ZZ1';
--extent#= 0 file#= 6 block#= 9
--extent#= 1 file#= 6 block#= 14
***************************************************************************************************************************************************************
第02部分-从数据字典查找zz1的段头块
02.1-为何表空间第一个段的bolck_id直接从9开始?
块1是OS文件头信息,块2是oracle文件头信息,块3~8表空间级的Bitmap块
SYS@10G> set pagesize 0
select file_id,block_id from dba_extents where owner='SYS' and segment_name='ZZ1' and extent_id=0;
6 9
02.2-补充:为何段头块从extent0的第3个块开始
一、为什么extent0中段头前面浪费掉9,10两个块?
SYS@10G> select HEADER_FILE,HEADER_BLOCK from dba_segments where owner='SYS' and segment_name='ZZ1';
6 11
块9=段级的Bitmap块= L1 BMB,块10=段级的Bitmap块=L2 BMB
二、补充:ASSM段Extent 0 的布局
1、每个L3中,有多个L2的地址(第一个L3是段头)。
2、每个L2中,有多个L1的地址。
3、每个L1中,有多个数据块地址。
*************************************************************************************************************************************************************
第03部分-从段头L3 BMB查找的L2 BMB
03.1-段内L2 BMB清单+Insert时查找的起点L2
一、DUMP段头块
SYS@10G>
set sqlprompt "_user'@'10G> "
conn / as sysdba
alter system checkpoint;
alter system dump datafile 6 block 11;
oradebug setmypid
oradebug tracefile_name
-- /u01/app/oracle/admin/orcl/udump/orcl_ora_5214.trc
SYS@10G> host grep type /u01/app/oracle/admin/orcl/udump/orcl_ora_5214.trc
frmt: 0x02 chkval: 0x5110 type: 0x23=PAGETABLE SEGMENT HEADER段头块
二、从段头L3 BMB查找的L2 BMB
1、管理了几个L2 BMB(nl2: 1)
SYS@10G> host grep -E -i 'nl2' /u01/app/oracle/admin/orcl/udump/orcl_ora_5214.trc
Segment Type: 1 nl2: 1 blksz: 8192 fbsz: 0
2、L3 BMB清单(仅一条:段头L3 BMB能容纳故不需创建新的First Level 3 BMB)
SYS@10G>host grep DBAs -A8 /u01/app/oracle/admin/orcl/udump/orcl_ora_5214.trc
Second Level Bitmap block DBAs
--------------------------------------------------------
DBA 1: 0x0180000a
End dump data blocks tsn: 7 file#: 6 minblk 11 maxblk 11
SYS@10G> select '--file#='||dbms_utility.data_block_address_file(TO_NUMBER('0180000a', 'XXXXXXXX')) ,
'block#='||dbms_utility.data_block_address_block(TO_NUMBER('0180000a', 'XXXXXXXX')) from dual;
--file#=6 block#=10(可dump 这个L2 BMB看哪个L1 BMB有空闲)
3、补充、最近生成的BMB
SYS@10G> host grep -E 'First Level |Last Level' /u01/app/oracle/admin/orcl/udump/orcl_ora_5214.trc
First Level 3 BMB: 0x00000000(库超大、区超多、块超多时才出现)
Last Level 1 BMB: 0x01c01ada(最后一个L1 BMB的地址)
Last Level II BMB: 0x0180000a(最后一个L2 BMB的地址)
Last Level III BMB: 0x0000000 (最后一个L3 BMB的地址)
三、Insert时从哪个L2 BMB中开始查找空闲空间——L2 hint
SYS@10G> host grep -E -i 'hint' /u01/app/oracle/admin/orcl/udump/orcl_ora_5214.trc
L2 Hint for inserts: 0x0180000a
SYS@10G> select '--file#='||dbms_utility.data_block_address_file(TO_NUMBER('0180000a', 'XXXXXXXX')) ,
'block#='||dbms_utility.data_block_address_block(TO_NUMBER('0180000a', 'XXXXXXXX')) from dual;
--file#=6 block#=10(可dump 这个L2 BMB看哪个L1 BMB有空闲)
03.2-补充:辅助区地图有区号与L1块的对照表
一、 Extent Map清单:描述区的块数和第一个块地址
SYS@10G> host grep -E 'Extent Map' -A3 /u01/app/oracle/admin/orcl/udump/orcl_ora_5214.trc
Extent Map 区地图
-----------------------------------------------------------------
0x01800009 length: 5
0x01c00009 length: 5
二、Auxlillary Map清单:描述区由哪个L1管理和非Metadata块始地址
SYS@10G> host grep -E 'Auxillary Map' -A3 /u01/app/oracle/admin/orcl/udump/orcl_ora_5214.trc
Auxillary Map
--------------------------------------------------------
Extent 0 : L1 dba: 0x01800009 Data dba: 0x0180000c(区0属于L1 BMB +区0第一个非Meta块的地址)
Extent 1 : L1 dba: 0x01800009 Data dba: 0x01c00009(区0属于L1 BMB +区1第一个非Meta块的地址)
说明:辅助区地址可看出哪几个区内的块共用同一个L1
-如果区比较小,一个L1中可以包含多个区中的块
-如果区比较大,多个L1共同包含一个个区中的块
三、根据辅助区地图找出L1 BMB地址
Extent 0 : L1 dba: 0x01800009 Data dba: 0x0180000c
=> L1 dba: 0x01800009
=> select '--'||dbms_utility.data_block_address_file(TO_NUMBER('01800009', 'XXXXXXXX')) file_id,
dbms_utility.data_block_address_block(TO_NUMBER('01800009', 'XXXXXXXX')) block_id from dual;
--6 9
*************************************************************************************************************************************************
第04部分-从L2 BMB中找出L1 BMB
04.1-哪个L1 BMB有可用块
一、DUMP块10
SYS@10G>
set sqlprompt "_user'@'10G> "
conn / as sysdba
alter system checkpoint;
alter system dump datafile 6 block 10;
oradebug setmypid
oradebug tracefile_name
--/u01/app/oracle/admin/orcl/udump/orcl_ora_4880.trc
二、L1BMB列表
1、L1BMB清单
SYS@10G> host grep 'L1 Ranges' -A222 /u01/app/oracle/admin/orcl/udump/orcl_ora_4880.trc|grep '0x'|head -3
0x01800009 Free: 1 Inst: 1
0x01c0000e Free: 1 Inst: 1
0x01800018 Free: 1 Inst: 1
2、L1BMB统计
SYS@10G> host grep 'L1 Ranges' -A222 /u01/app/oracle/admin/orcl/udump/orcl_ora_4880.trc|grep '0x'|wc -l
--160 有160个L1
3、从L2 BMB中找出第一个L1 BMB
SYS@10G> host grep 'L1 Ranges' -A222 /u01/app/oracle/admin/orcl/udump/orcl_ora_4880.trc|grep '0x'|head -n 1
0x01800009 Free: 1 Inst: 1
SYS@10G> select '--file#='||dbms_utility.data_block_address_file(TO_NUMBER('01800009', 'XXXXXXXX')) ,
'block#='||dbms_utility.data_block_address_block(TO_NUMBER('0180000a', 'XXXXXXXX')) from dual;
--file#=6 block#=10
三、有几个L1 BMB有Free块空间
1、从L2 BMB的汇总信息中查看
SYS@10G> host grep number: /u01/app/oracle/admin/orcl/udump/orcl_ora_4880.trc|grep -vi oracle
number: 160 nfree: 1ffree: 159 pdba: 0x0180000b
number=160—— 有160个L1
nfree=001——— 有1个L1中有可用块
ffree=159—— 有159个L1无可用块
2、用linux脚本过滤判断trace文件
SYS@10G> host grep 'L1 Ranges' -A222 /u01/app/oracle/admin/orcl/udump/orcl_ora_4880.trc|grep 'Free: \<[^1]\>'
--0x01c01ada Free: 5 Inst: 1
04.2-补充:L2指向L3的指针
一、块10是L2 BMB
SYS@10G> host grep type /u01/app/oracle/admin/orcl/udump/orcl_ora_4880.trc
frmt: 0x02 chkval: 0x4fce type: 0x21=SECOND LEVEL BITMAP BLOCK
二、块10指向L3 BMB的指针
1、0x0180000b =>0b=>11号块
SYS@10G> host grep pdba /u01/app/oracle/admin/orcl/udump/orcl_ora_4880.trc
number: 160 nfree: 1 ffree: 159 pdba: 0x0180000b
SYS@10G> set pagesize 0
select '--file#='||dbms_utility.data_block_address_file(TO_NUMBER('0180000b', 'XXXXXXXX')) ,
'block#='||dbms_utility.data_block_address_block(TO_NUMBER('0180000b', 'XXXXXXXX')) from dual;
--file#=6 block#=11
2、上层指针地址恰好是是段头块(除非数据库超大,有多个L3 BMB)
SQL> set pagesize 0
select HEADER_FILE,HEADER_BLOCK from dba_segments where segment_name='ZZ1';
6 11
***********************************************************************************************************************************************
第05部分-从L1 BMB找可用块
05.1-从L1 BMB找第一个可用块
一、找到 L1 BMB并DUMP
SYS@10G> set sqlprompt "_user'@'10G> "
set linesize 333
set pagesize 0
select '--File#='||file_id,'Block#='||block_id from dba_extents where segment_name='ZZ1';
--File#=6 Block#=9
--File#=6 Block#=14
SYS@10G>
conn / as sysdba
alter system checkpoint;
alter system dump datafile 6 block 9;
oradebug setmypid
oradebug tracefile_name
--/u01/app/oracle/admin/orcl/udump/orcl_ora_4866.trc
二、在L1 BMB中查看块状态
SYS@10G> host grep 'First free' /u01/app/oracle/admin/orcl/udump/orcl_ora_4866.trc
First free datablock : 5
SYS@10G> host grep 'DBA Ranges' -A8 /u01/app/oracle/admin/orcl/udump/orcl_ora_4866.trc
DBA Ranges :
--------------------------------------------------------
0x01800009 Length: 5 Offset: 0
0x0180000e Length: 5 Offset: 5
0:Metadata 1:Metadata 2:Metadata 3:FULL --3,4 两个区是FULL的
4:FULL 5:75-100% free 6:75-100% free 7:75-100% free
8:50-75% free 9:75-100% free --5,6,7,8,9是半free的
-------------------------------------------------
补充:Characteristics of Bitmap Segment Management
Bitmap space management uses four bits inside each data block header to indicate the amount of available space in the data block.
Unlike traditional space management with a fixed relink and unlink threshold, bitmap space managements allow Oracle to compare the actual row space for an INSERT with the actual available space on the data block.
This enables better reuse of the available free space especially for objects with rows of highly varying size. Here are the values inside the four-bit space:
三、truncate后重新在L1中查找第一个可用块并对比块的状态(L1块清单:3变为未格式化)
1、truncate并重新dump
SYS@10G> truncate table zz1;
conn / as sysdba
alter system checkpoint;
alter system dump datafile 6 block 9;
oradebug setmypid
oradebug tracefile_name
--/u01/app/oracle/admin/orcl/udump/orcl_ora_7056.trc
2、在L1中查找第一个可用块
SYS@10G> host grep -i -E 'free|meta' /u01/app/oracle/admin/orcl/udump/orcl_ora_7056.trc
First free datablock : 3
#blocks in seg. hdr's freelists: 0
0:Metadata 1:Metadata 2:Metadata 3:unformatted 原来占用的3和4两个区已被释放
--trucate前的状态:3,4 两个区是FULL的;5,6,7,8,9是半free的
四、insert后重新在L1中查找第一个可用块并对比块的状态(L1中块清单:新格了2个块)
1、insert并重新dump
SYS@10G> conn / as sysdba
alter system checkpoint;
alter system dump datafile 6 block 9;
oradebug setmypid
oradebug tracefile_name
-- /u01/app/oracle/admin/orcl/udump/orcl_ora_6616.trc
2、在L1中查找第一个可用块
SYS@10G> host grep -i -E 'free|meta' /u01/app/oracle/admin/orcl/udump/orcl_ora_6616.trc
First free datablock : 3
#blocks in seg. hdr's freelists: 0
0:Metadata 1:Metadata 2:Metadata 3:75-100% free
4:75-100% free
--以下是insert前的状态:0:Metadata 1:Metadata 2:Metadata 3:unformatted
05.2-补充:L1 BMB进一步解读
一、块的类型=L1 BMB
SYS@10G> host grep type /u01/app/oracle/admin/orcl/udump/orcl_ora_4866.trc
frmt: 0x02 chkval: 0x4f0a type: 0x20=FIRST LEVEL BITMAP BLOCK
二、上级位图块(L2 BMB)的地址0a=>10
SYS@10G> host grep -i parent /u01/app/oracle/admin/orcl/udump/orcl_ora_4866.trc
nbits : 4 nranges: 2管理了两个区 parent dba: 0x0180000a poffset: 0
SYS@10G> set pagesize 0
select '--file#='||dbms_utility.data_block_address_file(TO_NUMBER('0180000a', 'XXXXXXXX')) ,
'block#='||dbms_utility.data_block_address_block(TO_NUMBER('0180000a', 'XXXXXXXX')) from dual;
--file#=6 block#=10
三、BMB属于哪个段
SYS@10G> host grep -i objd /u01/app/oracle/admin/orcl/udump/orcl_ora_4866.trc
--Inc #: 0 Objd: 51451 对像号
SYS@10G> select '--object_name='||object_name from dba_objects where object_id=51451;
--object_name=ZZ1 对象名
四、BMB所管理的块的总数=10
SYS@10G> host grep -i unformatted /u01/app/oracle/admin/orcl/udump/orcl_ora_4866.trc
unformatted: 0 total: 10 first useful block: 3
1、unformatted: 0——低水位与高水位之间未格式化的块
2、total: 10——L1 BMB共管理了10个块
3、first useful block: 3第一个可以使用的块,9+0,9+1,9+2为段头、L1、L2和L3块等metadata块
*******************************************************************************************************************************************
第06部分- 补充Insert查找可用块原理
06.1-Insert查找可用块原理
一、→通过数据字典找到段头L3 BMB
二、→在L3 BMB中寻找可用L2 BMB
从哪个L2 BMB中开始查找空闲空间
L2 Hint for inserts: 0x0180000a
SYS@10G> select '--file#='||dbms_utility.data_block_address_file(TO_NUMBER('0180000a', 'XXXXXXXX')) ,
'block#='||dbms_utility.data_block_address_block(TO_NUMBER('0180000a', 'XXXXXXXX')) from dual;
--file#=6 block#=10
三、→在L2中找到寻找可用L1 BMB
——0x01c01ada Free: 5 Inst: 1
SYS@10G> host grep 'L1 Ranges' -A222 /u01/app/oracle/admin/orcl/udump/orcl_ora_4880.trc|grep '0x'|wc -l
160 L1BMB的数量
SYS@10G> host grep 'L1 Ranges' -A222 /u01/app/oracle/admin/orcl/udump/orcl_ora_4880.trc|grep '0x'|tail -n2
0x01800a4a Free: 1 Inst: 1 L1 BMB的清单
0x01c01ada Free: 5 Inst: 1 Free=5
四、→在L1中查找一个可用区及可用块(可能前面的区有未格式化的块,后面的区已使用)
(→DBA可dump 这个L1块,进一步查看哪个L1 BMB有空闲空间)
五、→在可用数据块插入新行。
06.2-补充:全表扫描原理
一、两个高水位:HWM与Low HWM
1、若L2有两个L1,插入行时会随机选择哪个L1
根据Server进程的PID值,进行HASH运算,得到一个HASH值,跟据此HSAH值决定选择哪个L1。
2、非顺序随机选择可用块造成的问题
→可能前面的区有未格式化的块,后面的区已使用
→LHWM与HHWM 之间可能存在formated block也可以可能存在unformatted block
二、全表扫描原理
SYS@10G> host grep HighWater -A 6 /u01/app/oracle/admin/orcl/udump/orcl_ora_5214.trc
Low HighWater Mark :
Highwater:: 0x01c01ae4 ext#: 1905 blk#: 5 ext size: 5
#blocks in seg. hdr's freelists: 0
#blocks below: 9367
mapblk 0x01800a13 offset: 74
Level 1 BMB for High HWM block: 0x01c01ada(与HHWM最近的L1)
Level 1 BMB for Low HWM block: 0x01c01ada(与LHWM最近的L1)
1、通过数据字典找到段头
2、从段头块找全表扫描的起止点
起点:从区地图中找到
中点:低高水位级
止点:高主水位线
3、全表扫描时,通常都是读至低高水位线,然后根据位图去读低HWM与高HWM之间格式化过的块,避开未格式化的块