前言
段(segment)是一种在数据库中消耗物理存储空间的任何实体(一个段可能存在于多个数据文件中,因为物理的数据文件
是组成逻辑表空间的基本物理存储单位)
最近在学习段(segment)、区间(extent)时,对段的HEADER_BLOCK有一些疑问,本文记录一下探究的实验过程以及相关总结,,如有不对的地方,敬请指出。以SCOTT.EMP表为例(下面测试环境为Oracle Database 10g Release 10.2.0.5.0 - 64bit Production):
SELECT FILE_ID, BLOCK_ID, BLOCKS FROM DBA_EXTENTS WHERE OWNER =&OWNER AND SEGMENT_NAME = &TABLE_NAME;
SELECT HEADER_FILE , HEADER_BLOCK , BYTES , BLOCKS , EXTENTS FROM DBA_SEGMENTS WHERE OWNER=&OWNER AND SEGMENT_NAME=&SEGMENT_NAME;
如上所示,DBA_SEGMENTS 中的HEADER_BLOCK 与DBA_EXTENTS的BLOCK_ID不同(HEADER_BLOCK:文件ID为4的第27个块,区间的第一个块的BLOCK_ID为第25个块),这个的原因如下:
一个segment的第一个区的第一个块是FIRST LEVEL BITMAP BLOCK,第二个块是SECOND LEVEL BITMAP BLOCK,这两个块是用来管理free block的,第三个块是PAGETABLE SEGMENT HEADER,这个块才是segment里的HEADER_BLOCK,再后面的块就是用来记录数据的。所以25+2=27. 详细可以参考《循序渐进ORCLE:数据库管理、优化与备份》这本书的第5章。
下面我们创建一个表,测试一下是否也是这个规律,如下所示:
SQL> CREATE TABLE TEST1.MMM 2 AS 3 SELECT * FROM DBA_OBJECTS; Table created. SQL> COL SEGMENT_NAME FOR A32;SQL> SELECT SEGMENT_NAME 2 ,FILE_ID 3 ,BLOCK_ID 4 ,BLOCKS 5 FROM DBA_EXTENTS 6 WHERE SEGMENT_NAME=MMM AND OWNER=TEST1 7 ORDER BY BLOCK_ID ASC; SEGMENT_NAME FILE_ID BLOCK_ID BLOCKS-------------------------------- ---------- ---------- ----------MMM 76 9 8MMM 76 17 8MMM 76 25 8MMM 76 33 8MMM 76 41 8MMM 76 49 8MMM 76 57 8MMM 76 65 8MMM 76 73 8MMM 76 81 8MMM 76 89 8 SEGMENT_NAME FILE_ID BLOCK_ID BLOCKS-------------------------------- ---------- ---------- ----------MMM 76 97 8MMM 76 105 8MMM 76 113 8MMM 76 121 8MMM 76 129 8MMM 76 137 128MMM 76 265 128MMM 76 393 128MMM 76 521 128MMM 76 649 128MMM 76 777 128 22 rows selected. SQL> SELECT HEADER_FILE 2 , HEADER_BLOCK 3 , BYTES 4 , BLOCKS 5 , EXTENTS 6 FROM DBA_SEGMENTS 7 WHERE OWNER=TEST1 AND SEGMENT_NAME=MMM; HEADER_FILE HEADER_BLOCK BYTES BLOCKS EXTENTS----------- ------------ ---------- ---------- ---------- 76 11 7340032 896 22
如上所示,段对象TEST1.MMM的header_block为11 ,而对应的区间的第一个块对象ID为9, 也是9+2=11,确实是如此,那么我们来DUMP数据块看看,如下所示
SQL> alter system dump datafile 76 block 9; System altered. SQL> alter system dump datafile 76 block 10; System altered. SQL> alter system dump datafile 76 block 11; System altered. SQL> select user_dump.value 2 || / 3 || lower(instance.value) 4 || _ora_ 5 || v$process.spid 6 || nvl2(v$process.traceid, _ 7 || v$process.traceid, null) 8 || .trc"trace file" 9 from v$parameter user_dump 10 cross join v$parameter instance 11 cross join v$process 12 join v$session 13 on v$process.addr = v$session.paddr 14 where user_dump.name = user_dump_dest 15 and instance.name = instance_name 16 and v$session.audsid = sys_context(userenv, sessionid); trace file--------------------------------------------------------------------------------/u01/app/oracle/admin/SCM2/udump/scm2_ora_22642.trc
第一个区的第一个块(block_id=9)是FIRST LEVEL BITMAP BLOCK,第二个块(block_id=10)是SECOND LEVEL BITMAP BLOCK,这两个块是用来管理free block的,第三个块(block_id=11)是PAGETABLE SEGMENT HEADER,这个块才是segment里的HEADER_BLOCK,再后面的块就是用来记录数据的
不过有一个奇怪的现象,对SCOTT.EMP其数据块做dump,发现25、26、27数据块的type都是trans data,0x06表示的Block Type为 Table/cluster/index segment data block 。 不知是否因为SCOTT.EMP对象位于USERS表空间下的缘故。不过USER表空间也是ASSM管理的。具体情况尚不清楚?
SQL> SELECT TABLESPACE_NAME 2 , SEGMENT_SPACE_MANAGEMENT 3 , ALLOCATION_TYPE 4 , EXTENT_MANAGEMENT 5 FROM DBA_TABLESPACES 6 WHERE TABLESPACE_NAME=USERS; TABLESPACE_NAME SEGMEN ALLOCATIO EXTENT_MAN------------------------------ ------ --------- ----------USERS AUTO SYSTEM LOCAL
那么是否所有的HEADER_BLOCK都是位于段的第三个block呢?是否还跟段空间管理的方式有关呢? 我们用如下实验来探究一下:创建一个手工段空间管理(Manual Segment Space Management)的表空间。
SQL> CREATE TABLESPACE TBS_TEST_DATA 2 DATAFILE /u03/oradata/gsp/tbs_test_data_001.dbf 3 SIZE 20M 4 EXTENT MANAGEMENT LOCAL AUTOALLOCATE 5 SEGMENT SPACE MANAGEMENT MANUAL ONLINE; Tablespace created. SQL> create user test identified by test123456 2 default tablespace tbs_test_data; User created. SQL> grant connect, resource to test; Grant succeeded. SQL> CREATE TABLE TEST.KKK 2 AS 3 SELECT * FROM DBA_OBJECTS; Table created. SQL> COL SEGMENT_NAME FOR A32;SQL> SELECT SEGMENT_NAME 2 ,FILE_ID 3 ,BLOCK_ID 4 ,BLOCKS 5 FROM DBA_EXTENTS 6 WHERE SEGMENT_NAME=KKK AND OWNER=TEST 7 ORDER BY BLOCK_ID ASC; SEGMENT_NAME FILE_ID BLOCK_ID BLOCKS-------------------------------- ---------- ---------- ----------KKK 39 427785 128KKK 43 435249 8KKK 43 435257 8KKK 43 435265 8KKK 43 435273 8KKK 43 435281 8KKK 43 435289 8KKK 43 435297 8KKK 43 435305 8KKK 43 435313 8KKK 43 435321 8 SEGMENT_NAME FILE_ID BLOCK_ID BLOCKS-------------------------------- ---------- ---------- ----------KKK 43 435329 8KKK 48 436745 8KKK 48 436753 8KKK 48 436761 8KKK 48 436769 8KKK 48 436777 8KKK 48 436873 128KKK 40 444297 128KKK 43 447241 128KKK 52 449545 128KKK 2 458249 128 22 rows selected. SQL> SELECT HEADER_FILE 2 , HEADER_BLOCK 3 , BYTES 4 , BLOCKS 5 , EXTENTS 6 FROM DBA_SEGMENTS 7 WHERE OWNER=TEST AND SEGMENT_NAME=KKK; HEADER_FILE HEADER_BLOCK BYTES BLOCKS EXTENTS----------- ------------ ---------- ---------- ---------- 43 435249 7340032 896 22 SQL>
SQL> alter system dump datafile 43 block 435249; System altered. SQL> select user_dump.value 2 || / 3 || lower(instance.value) 4 || _ora_ 5 || v$process.spid 6 || nvl2(v$process.traceid, _ 7 || v$process.traceid, null) 8 || .trc"trace file" 9 from v$parameter user_dump 10 cross join v$parameter instance 11 cross join v$process 12 join v$session 13 on v$process.addr = v$session.paddr 14 where user_dump.name = user_dump_dest 15 and instance.name = instance_name 16 and v$session.audsid = sys_context(userenv, sessionid); trace file--------------------------------------------------------------------/u01/app/oracle/admin/SCM2/udump/scm2_ora_27792.trc
如下所示,块类型为DATA SEGEMENT HEADER -UNLIMITED , rdba:( segment header的块地址为)为 0x0ac6a431 .其实这是第一个块(不是以block_id大小来看),因为手工段空间管理,这种技术的具体实现方式是通过在段头(Segment Header)分配自由列表(freelist)来管理Block的使用。简单一点,你可以把自由列表想象成一个数据结构中的链表一样的数据结构,ORACLE通过一系列算法向自由列表(freelist)中加入或移出Block来实现段管理。
Segment Header是一个Segment的第一个extent的头块(第一个块)。在FLM管理的Segment中,header block始终是segment 的第一个块。 如下所示,在Extent Map中,第一个区间的地址为0x0ac6a432, 恰恰跟segment header的块地址 0x0ac6a431 相差为1,这意味着后面的分配是紧挨着segment header的块地址。 所以在手工段空间管理(Manual Segment Space Management)的表空间,不能以block_id的大小顺序来看区间分配顺序。也就是说FILE_ID=39 BLOCK_ID=427785的块并不是第一个区间的第一个块。这也是我在实验当中纠结了好久的地方。
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对脚本之家的支持。