前言
段(segment)是一種在數(shù)據(jù)庫中消耗物理存儲空間的任何實體(一個段可能存在于多個數(shù)據(jù)文件中,因為物理的數(shù)據(jù)文件
是組成邏輯表空間的基本物理存儲單位)
最近在學習段(segment)、區(qū)間(extent)時,對段的HEADER_BLOCK有一些疑問,本文記錄一下探究的實驗過程以及相關總結,,如有不對的地方,敬請指出。以SCOTT.EMP表為例(下面測試環(huán)境為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個塊,區(qū)間的第一個塊的BLOCK_ID為第25個塊),這個的原因如下:
一個segment的第一個區(qū)的第一個塊是FIRST LEVEL BITMAP BLOCK,第二個塊是SECOND LEVEL BITMAP BLOCK,這兩個塊是用來管理free block的,第三個塊是PAGETABLE SEGMENT HEADER,這個塊才是segment里的HEADER_BLOCK,再后面的塊就是用來記錄數(shù)據(jù)的。所以25+2=27. 詳細可以參考《循序漸進ORCLE:數(shù)據(jù)庫管理、優(yōu)化與備份》這本書的第5章。
下面我們創(chuàng)建一個表,測試一下是否也是這個規(guī)律,如下所示:
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 ,而對應的區(qū)間的第一個塊對象ID為9, 也是9+2=11,確實是如此,那么我們來DUMP數(shù)據(jù)塊看看,如下所示
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
第一個區(qū)的第一個塊(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,再后面的塊就是用來記錄數(shù)據(jù)的
不過有一個奇怪的現(xiàn)象,對SCOTT.EMP其數(shù)據(jù)塊做dump,發(fā)現(xiàn)25、26、27數(shù)據(jù)塊的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呢?是否還跟段空間管理的方式有關呢? 我們用如下實驗來探究一下:創(chuàng)建一個手工段空間管理(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大小來看),因為手工段空間管理,這種技術的具體實現(xiàn)方式是通過在段頭(Segment Header)分配自由列表(freelist)來管理Block的使用。簡單一點,你可以把自由列表想象成一個數(shù)據(jù)結構中的鏈表一樣的數(shù)據(jù)結構,ORACLE通過一系列算法向自由列表(freelist)中加入或移出Block來實現(xiàn)段管理。
Segment Header是一個Segment的第一個extent的頭塊(第一個塊)。在FLM管理的Segment中,header block始終是segment 的第一個塊。 如下所示,在Extent Map中,第一個區(qū)間的地址為0x0ac6a432, 恰恰跟segment header的塊地址 0x0ac6a431 相差為1,這意味著后面的分配是緊挨著segment header的塊地址。 所以在手工段空間管理(Manual Segment Space Management)的表空間,不能以block_id的大小順序來看區(qū)間分配順序。也就是說FILE_ID=39 BLOCK_ID=427785的塊并不是第一個區(qū)間的第一個塊。這也是我在實驗當中糾結了好久的地方。
總結
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。
您可能感興趣的文章:- oracle刪除表字段和oracle表增加字段
- oracle使用sql語句增加字段示例(sql刪除字段語句)
- Oracle 插入超4000字節(jié)的CLOB字段的處理方法
- oracle關鍵字作為字段名使用方法
- 深入淺析mybatis oracle BLOB類型字段保存與讀取
- Oracle中判斷字段是否為數(shù)字
- 簡單三步輕松實現(xiàn)ORACLE字段自增
- oracle數(shù)據(jù)庫中如何處理clob字段方法介紹
- Oracle 查詢表信息獲取表字段及字段注釋
- java讀寫oracle的blob字段示例