好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

ORACLE中段的HEADER_BLOCK示例详析

前言

段(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

查看更多关于ORACLE中段的HEADER_BLOCK示例详析的详细内容...

  阅读:30次