• ORACLE关于段的HEADER_BLOCK的一点浅析


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

    clip_image001

    SELECT HEADER_FILE
         , HEADER_BLOCK
         , BYTES
         , BLOCKS
         , EXTENTS 
    FROM DBA_SEGMENTS 
    WHERE OWNER='&OWNER' AND SEGMENT_NAME='&SEGMENT_NAME';

     

    clip_image002

     

    如上所示,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,再后面的块就是用来记录数据的

    clip_image003

    clip_image004

    clip_image005

     

    不过有一个奇怪的现象,对SCOTT.EMP其数据块做dump,发现25、26、27数据块的type都是trans data,0x06表示的Block Type为 Table/cluster/index segment data block 。 不知是否因为SCOTT.EMP对象位于USERS表空间下的缘故。不过USER表空间也是ASSM管理的。具体情况尚不清楚?

    clip_image006

     

    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> 

    clip_image007

     

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

     

    image

     

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

     

    image

     

    参考资料:

     

    http://blog.chinaunix.net/uid-7628732-id-119768.html

    http://www.eygle.com/archives/2007/07/oracle_assm_level3_bmb.html

    《循序渐进ORACLE:数据库管理、优化与备份》

  • 相关阅读:
    [hdu2196]Computer树的直径
    [poj2342]Anniversary party树形dp入门
    链式前向星模板
    LintCode-50.数组剔除元素后的乘积
    Markdown的基本语法
    LintCode-8.旋转字符串
    LintCode-1.A + B 问题
    LintCode-61.搜索区间
    LintCode-88.最近公共祖先
    LintCode-54.转换字符串到整数
  • 原文地址:https://www.cnblogs.com/kerrycode/p/6856582.html
Copyright © 2020-2023  润新知