• 企业400电话
  • 微网小程序
  • AI电话机器人
  • 电商代运营
  • 全 部 栏 目

    企业400电话 网络优化推广 AI电话机器人 呼叫中心 网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    ORACLE中段的HEADER_BLOCK示例详析

    前言

    段(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   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,再后面的块就是用来记录数据的

    不过有一个奇怪的现象,对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  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> 

     

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

    总结

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

    您可能感兴趣的文章:
    • oracle删除表字段和oracle表增加字段
    • oracle使用sql语句增加字段示例(sql删除字段语句)
    • Oracle 插入超4000字节的CLOB字段的处理方法
    • oracle关键字作为字段名使用方法
    • 深入浅析mybatis oracle BLOB类型字段保存与读取
    • Oracle中判断字段是否为数字
    • 简单三步轻松实现ORACLE字段自增
    • oracle数据库中如何处理clob字段方法介绍
    • Oracle 查询表信息获取表字段及字段注释
    • java读写oracle的blob字段示例
    上一篇:ORACLE检查找出损坏索引(Corrupt Indexes)的方法详解
    下一篇:Oracle 闪回 找回数据的实现方法
  • 相关文章
  • 

    © 2016-2020 巨人网络通讯 版权所有

    《增值电信业务经营许可证》 苏ICP备15040257号-8

    ORACLE中段的HEADER_BLOCK示例详析 ORACLE,中段,的,HEADER,BLOCK,