欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

ORACLE中段的HEADER_BLOCK示例详析

程序员文章站 2022-06-24 22:05:58
前言 段(segment)是一种在数据库中消耗物理存储空间的任何实体(一个段可能存在于多个数据文件中,因为物理的数据文件 是组成逻辑表空间的基本物理存储单位) 最...

前言

段(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'; 

ORACLE中段的HEADER_BLOCK示例详析 

select header_file
  , header_block
  , bytes
  , blocks
  , extents 
from dba_segments 
where owner='&owner' and segment_name='&segment_name';

ORACLE中段的HEADER_BLOCK示例详析

如上所示,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   8
mmm          76   17   8
mmm          76   25   8
mmm          76   33   8
mmm          76   41   8
mmm          76   49   8
mmm          76   57   8
mmm          76   65   8
mmm          76   73   8
mmm          76   81   8
mmm          76   89   8
 
segment_name      file_id block_id  blocks
-------------------------------- ---------- ---------- ----------
mmm          76   97   8
mmm          76  105   8
mmm          76  113   8
mmm          76  121   8
mmm          76  129   8
mmm          76  137  128
mmm          76  265  128
mmm          76  393  128
mmm          76  521  128
mmm          76  649  128
mmm          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,再后面的块就是用来记录数据的

ORACLE中段的HEADER_BLOCK示例详析

ORACLE中段的HEADER_BLOCK示例详析

ORACLE中段的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管理的。具体情况尚不清楚?

ORACLE中段的HEADER_BLOCK示例详析

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  128
kkk          43  435249   8
kkk          43  435257   8
kkk          43  435265   8
kkk          43  435273   8
kkk          43  435281   8
kkk          43  435289   8
kkk          43  435297   8
kkk          43  435305   8
kkk          43  435313   8
kkk          43  435321   8
 
segment_name      file_id block_id  blocks
-------------------------------- ---------- ---------- ----------
kkk          43  435329   8
kkk          48  436745   8
kkk          48  436753   8
kkk          48  436761   8
kkk          48  436769   8
kkk          48  436777   8
kkk          48  436873  128
kkk          40  444297  128
kkk          43  447241  128
kkk          52  449545  128
kkk          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> 

ORACLE中段的HEADER_BLOCK示例详析 

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来实现段管理。

ORACLE中段的HEADER_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的块并不是第一个区间的第一个块。这也是我在实验当中纠结了好久的地方。

ORACLE中段的HEADER_BLOCK示例详析

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对的支持。