ITPub博客

首页 > Linux操作系统 > Linux操作系统 > 高水位线HWM到底在哪儿?

高水位线HWM到底在哪儿?

原创 Linux操作系统 作者:realkid4 时间:2012-03-13 22:38:26 0 删除 编辑

 

高水位线是Oracle段对象的一个重要参数。对Oracle Segment对象而言,HWMHigh Water Mark)标记着数据使用过的最高位置,有时也称为格式化过的数据位置。

 

Oracle数据表进行FTS(全表扫描)操作的时候,会从段头一直检索到HWM位置。本篇中,我们一起从逻辑结构分析的角度,来研究一下HWM的确切位置。

 

1、环境准备

 

我们选择在Oracle 10g下进行试验,准备数据表T

 

 

SQL> select * from v$version;

BANNER

----------------------------------------------------------------

Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod

PL/SQL Release 10.2.0.1.0 - Production

CORE     10.2.0.1.0       Production

 

SQL> show user

User is "SYS"

 

SQL> create table t as select * from dba_objects;

Table created

 

SQL> exec dbms_stats.gather_table_stats(user,'T',cascade => true);

PL/SQL procedure successfully completed

 

 

2、原始HWM位置分析

 

根据Oracle“表---块”的层次顺序,分析一下对应数据表的情况。

 

 

SQL> select HEADER_FILE, HEADER_BLOCK, BYTES, BLOCKS, EXTENTS from dba_segments where wner='SYS' and segment_name='T';

 

HEADER_FILE HEADER_BLOCK      BYTES     BLOCKS    EXTENTS

----------- ------------ ---------- ---------- ----------

          1        63057    6291456        768         21

 

 

 

对应768个数据块,包括21个分区中。

 

 

SQL> select EXTENT_ID, FILE_ID, BLOCK_ID, BYTES, BLOCKS from dba_extents where wner='SYS' and segment_name='T';

 

 EXTENT_ID    FILE_ID   BLOCK_ID      BYTES     BLOCKS

---------- ---------- ---------- ---------- ----------

         0          1      63057      65536          8

(篇幅原因,有省略……

        19          1      63881    1048576        128

        20          1      64009    1048576        128

 

21 rows selected

 

 

Oraclesegment的空间分配,是按照一个extent一个extent进行的。当当前的extent使用完,并且没有可以使用的空间时,Oracle会给segment一个新的extent使用,分配新的extent_id编号。

 

HWM记录的位置是在数据段segment的段头块中。我们通过dba_segments视图,可以知道对应的段头块为fno=1blockno=63057。我们使用dump命令,可以将其逻辑结构展现出来。

 

 

SQL> select f_get_trace_name from dual;

 

F_GET_TRACE_NAME

--------------------------------------------------------------------------------

D:\ADMIN\ORCL\UDUMP\orcl_ora_1984.trc

 

SQL> alter system dump datafile 1 block 63057;

System altered

 

 

trace文件中,我们找到HWM位置记录和对应的Extent分配map

 

 

Extent Header:: spare1: 0      spare2: 0      #extents: 21     #blocks: 767  

                  last map  0x00000000  #maps: 0      offset: 4128 

      Highwater::  0x0040fa42  ext#: 20     blk#: 57     ext size: 128  

  #blocks in seg. hdr's freelists: 0    

  #blocks below: 696  

  mapblk  0x00000000  offset: 20   

                   Unlocked

     Map Header:: next  0x00000000  #extents: 21   obj#: 56436  flag: 0x40000000

  Extent Map

  -----------------------------------------------------------------

   0x0040f652  length: 7    

   0x0040f659  length: 8    

   (篇幅原因,省略…..

   0x0040f909  length: 128  

   0x0040f989  length: 128  

   0x0040fa09  length: 128 

 

 

extent allocation map中,我们可以看到对应的21extents使用分配情况。段头块中记录着HWM的位置地址,其中的(Highwater::  0x0040fa42)就表示这个具体位置。

 

注意:当Oracle要进行FTS的时候,首先访问的就是段头segment header块。从其中,可以获得分配的分区信息(Map Header)和Scan截止位置HWM

 

下面考虑解析HWM地址。在Oracle 10g中,我们可以使用dbms_utility包方法进行解析。

 

 

SQL> select to_number('40fa42','xxxxxx') from dual;

 

TO_NUMBER('40FA42','XXXXXX')

----------------------------

                     4258370

 

SQL> select dbms_utility.data_block_address_file(4258370) from dual;

 

DBMS_UTILITY.DATA_BLOCK_ADDRES

------------------------------

                             1

 

SQL> select dbms_utility.data_block_address_block(4258370) from dual;

 

DBMS_UTILITY.DATA_BLOCK_ADDRES

------------------------------

                         64066

 

 

可以知道,对应HWM指向的位置是在文件编号为1的文件中,对应块号为64066

 

那么,我们检查一下这个位置在哪里。

 

 

SQL> select EXTENT_ID, FILE_ID, BLOCK_ID, BYTES, BLOCKS from dba_extents where wner='SYS' and segment_name='T' and (block_id<=64066 and block_id+blocks-1>=64066) and file_id=1;

 

 EXTENT_ID    FILE_ID   BLOCK_ID      BYTES     BLOCKS

---------- ---------- ---------- ---------- ----------

        20          1      64009    1048576        128

 

 

对应的blockno=64066为最大extent编号下的一个数据块。我们可以看一下对应的相邻数据块中内容。

 

--高水位线对应数据块

SQL>  select count(*) from t where dbms_rowid.rowid_relative_fno(t.rowid)=1 and dbms_rowid.rowid_block_number(t.rowid)=64066;

  COUNT(*)

----------

         0

 

-高水位线对应上一个数据块

SQL>  select count(*) from t where dbms_rowid.rowid_relative_fno(t.rowid)=1 and dbms_rowid.rowid_block_number(t.rowid)=64065;

  COUNT(*)

----------

         1

 

---高水位线对应上上个数据块

SQL>  select count(*) from t where dbms_rowid.rowid_relative_fno(t.rowid)=1 and dbms_rowid.rowid_block_number(t.rowid)=64064;

  COUNT(*)

----------

        65

 

---高水位线对应下一个数据块

SQL>  select count(*) from t where dbms_rowid.rowid_relative_fno(t.rowid)=1 and dbms_rowid.rowid_block_number(t.rowid)=64067;

  COUNT(*)

----------

         0

 

 

从上面的数据,我们可以清晰的看到HWM的对应。HWM位于segment编号最大的extent中的一个数据块。在Oracle中,HWM对应的数据块是那个没有使用过的数据块。HWM上面的就是正在使用的最大数据块。

 

那么,我们观察一下,在添加和删除过程中,HWM的变化情况。

 

3HWM变化

 

下面我们观察一下HWMinsertdeletemove操作时候的变化。

 

当进行insert操作时,如果是一个heap表的话,首先会在堆中寻找空位插入。如果没有找到,就推高HWM到一个新的块位置。

 

我们继续在上面实验的基础上,进行试验。

 

 

SQL> insert into t select * from dba_objects where wner='SCOTT';

25 rows inserted

 

SQL> commit;

Commit complete

 

 

此时,我们dump出数据块查看HWM情况。

 

 

Extent Header:: spare1: 0      spare2: 0      #extents: 21     #blocks: 767  

                  last map  0x00000000  #maps: 0      offset: 4128 

      Highwater::  0x0040fa47  ext#: 20     blk#: 62     ext size: 128   

  #blocks in seg. hdr's freelists: 5    

  #blocks below: 701  

 

 

水位线位置从原来的0x0040fa42变化到0x0040fa47。真实对应的位置如下:

 

 

SQL> select to_number('40fa47','xxxxxx') from dual;

 

TO_NUMBER('40FA47','XXXXXX')

----------------------------

                     4258375

 

SQL> select dbms_utility.data_block_address_file(4258375) from dual;

 

DBMS_UTILITY.DATA_BLOCK_ADDRES

------------------------------

                             1

 

SQL> select dbms_utility.data_block_address_block(4258375) from dual;

 

DBMS_UTILITY.DATA_BLOCK_ADDRES

------------------------------

                         64071

 

 

对应从原来的64066块偏移到了64071块,移动了5个数据块。结论:确实insert操作可能会推高水位线位置。

 

那么,一般的delete操作呢?

 

 

SQL> delete t where wner='SCOTT';

50 rows deleted

 

SQL> commit;

Commit complete

 

SQL> alter system dump datafile 1 block 63057;

System altered

 

 

此时,HWM位置为:

 

 

Extent Control Header

  -----------------------------------------------------------------

  Extent Header:: spare1: 0      spare2: 0      #extents: 21     #blocks: 767  

                  last map  0x00000000  #maps: 0      offset: 4128 

      Highwater::  0x0040fa47  ext#: 20     blk#: 62     ext size: 128  

  #blocks in seg. hdr's freelists: 6    

  #blocks below: 701  

  mapblk  0x00000000  offset: 20   

                   Unlocked

     Map Header:: next  0x00000000  #extents: 21   obj#: 56436  flag: 0x40000000

 

 

数据HWM位置没有发生变化,说明HWM确实不会在delete的时候下降。

 

影响HWM下降的两个常见命令,MoveTruncate效果如何呢?

 

 

SQL> alter table t move;

Table altered

 

SQL> select HEADER_FILE, HEADER_BLOCK, BYTES, BLOCKS, EXTENTS from dba_segments where wner='SYS' and segment_name='T';

 

HEADER_FILE HEADER_BLOCK      BYTES     BLOCKS    EXTENTS

----------- ------------ ---------- ---------- ----------

          1        63441    6291456        768         21

 

 

此时,头块位置已经发生改变!!

 

 

SQL> alter system dump datafile 1 block 63441;

System altered

 

 

Move操作影响到了头块位置,HWM位置必然发生变化。

 

 

-----------------------------------------------------------------

  Extent Header:: spare1: 0      spare2: 0      #extents: 21     #blocks: 767  

                  last map  0x00000000  #maps: 0      offset: 4128 

      Highwater::  0x0040fd41  ext#: 20     blk#: 56     ext size: 128  

  #blocks in seg. hdr's freelists: 0    

  #blocks below: 695  

  mapblk  0x00000000  offset: 20   

      Disk Lock:: Locked by xid:  0x0006.007.000005a6

     Map Header:: next  0x00000000  #extents: 21   obj#: 56512  flag: 0x40000000

 

 

最后,我们一起看一下truncate table命令。

 

 

SQL> truncate table t;

Table truncated

 

SQL> select HEADER_FILE, HEADER_BLOCK, BYTES, BLOCKS, EXTENTS from dba_segments where wner='SYS' and segment_name='T';

 

HEADER_FILE HEADER_BLOCK      BYTES     BLOCKS    EXTENTS

----------- ------------ ---------- ---------- ----------

          1        63441      65536          8          1

 

 

注意:truncated table命令是不会影响到段头块的。

 

我们dump出头块情况。

 

 

SQL> alter system dump datafile 1 block 63441;

System altered

 

 

Dump出的数据块结构如下:

 

 

-----------------------------------------------------------------

  Extent Header:: spare1: 0      spare2: 0      #extents: 1      #blocks: 7    

                  last map  0x00000000  #maps: 0      offset: 4128 

      Highwater::  0x0040f7d2  ext#: 0      blk#: 0      ext size: 7    

  #blocks in seg. hdr's freelists: 0    

  #blocks below: 0    

  mapblk  0x00000000  offset: 0    

      Disk Lock:: Locked by xid:  0x0008.001.0000058b

     Map Header:: next  0x00000000  #extents: 1    obj#: 56513  flag: 0x40000000

  Extent Map

  -----------------------------------------------------------------

   0x0040f7d2  length: 7    

 

  nfl = 1, nfb = 1 typ = 1 nxf = 0 ccnt = 0

  SEG LST:: flg: UNUSED lhd: 0x00000000 ltl: 0x00000000

 

 

水位线下降到什么位置呢?我们计算一下这个:0x0040f7d2

 

 

SQL> select to_number('40f7d2','xxxxxx') from dual;

 

TO_NUMBER('40F7D2','XXXXXX')

----------------------------

                     4257746

 

SQL> select dbms_utility.data_block_address_block(4257746) from dual;

 

DBMS_UTILITY.DATA_BLOCK_ADDRES

------------------------------

                         63442

 

SQL> select dbms_utility.data_block_address_file(4257746) from dual;

 

DBMS_UTILITY.DATA_BLOCK_ADDRES

------------------------------

                             1

 

 

注意:这里的HWM指向块号为63442。我们的数据段头块为63441。说明:在truncate table的时候,HWM要重置到头块后面的第一个数据块上。

 

4、结论

 

经过上面的讨论,我们已经可以清晰的看到Oracle HWM的位置和工作原则。对segment对象而言,HWM的作用十分重要,需要我们深刻理解。

 

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/17203031/viewspace-718461/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
求道~

注册时间:2010-11-30

  • 博文量
    545
  • 访问量
    7645730