前言
段(segment)是一種在數據庫中消耗物理存儲空間的任何實體(一個段可能存在于多個數據文件中,因為物理的數據文件
是組成邏輯表空間的基本物理存儲單位)
最近在學習段(segment)、區間(extent)時,對段的HEADER_BLOCK有一些疑問,本文記錄一下探究的實驗過程以及相關總結,,如有不對的地方,敬請指出。以SCOTT.EMP表為例(下面測試環境為Oracle Database 10g Release 10.2.0.5.0 - 64bit Production):
1
2
3
4
5
6
|
SELECT FILE_ID, BLOCK_ID, BLOCKS FROM DBA_EXTENTS WHERE OWNER = '&OWNER' AND SEGMENT_NAME = '&TABLE_NAME' ; |
1
2
3
4
5
6
7
|
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章。
下面我們創建一個表,測試一下是否也是這個規律,如下所示:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
|
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數據塊看看,如下所示
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
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管理的。具體情況尚不清楚?
1
2
3
4
5
6
7
8
9
10
|
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)的表空間。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
|
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> |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
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的塊并不是第一個區間的第一個塊。這也是我在實驗當中糾結了好久的地方。
總結
以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對服務器之家的支持。
原文鏈接:http://www.cnblogs.com/kerrycode/p/6856582.html