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:數據庫管理、優化與備份》


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM