關於Freelists和Freelist Groups的研究(修訂版)- freelists儲存在哪兒

kamus發表於2005-03-09
三.             freelists儲存在哪兒
freelists儲存在每個segment的header block中,我們可以通過dump來得到更清楚的認識。dump在研究oracle的內部機制時通常都扮演著很重要的角色。
假設我們建立一個表空間TS_TEST,此表空間是非自動段空間管理的,然後在該表空間中建立T_MANUAL,T_MANUAL_FREE2,T_MANUAL_FREEGROUP2三張表。這三張表的freelists和freelist groups設定如下。
 
SQL> select SEGMENT_NAME,SEGMENT_TYPE,FREELISTS,FREELIST_GROUPS from USER_SEGMENTS where TABLESPACE_NAME='TS_TEST';
 
SEGMENT_NAME         SEGMENT_TYPE        FREELISTS FREELIST_GROUPS
-------------------- ------------------ ---------- ---------------
T_MANUAL             TABLE                       1               1
T_MANUAL_FREE2       TABLE                       2               1
T_MANUAL_FREEGROUP2  TABLE                       4               2
 
則可以參照下面的方法對segment header block進行dump操作。
首先先從資料字典中得到儲存這個segment的檔案號和此segment的第一個block號(也就是segment header block)
 
SQL> select FILE_ID,BLOCK_ID from dba_extents where segment_name='T_MANUAL';
 
   FILE_ID   BLOCK_ID
---------- ----------
         7          9
 
使用dump命令轉儲這個block的內容,轉儲的結果將儲存在初始化引數user_dump_dest指定的目錄中。
 
SQL> alter system dump datafile 7 block 9;
 
System altered
 
檢視user_dump_dest目錄中的相應trace檔案,我們可以看到包含如下幾行:
frmt: 0x02 chkval: 0x0000 type: 0x10=DATA SEGMENT HEADER – UNLIMITED
表示這個block正是segment header block。
#blocks in seg. hdr's freelists: 2    
#blocks below: 2
表示位於freelist中的資料塊有2個,在高水位標誌(HWM)下的資料塊也有2個。
SEG LST:: flg: USED   lhd: 0x01c0000a ltl: 0x01c0000b
由於我們dump的是TS_MANUAL表的header block,而這張表的freelists=1,所以在dump檔案中看到只有一個seg lst,這個freelist被稱為segment free list或者master free list,每個segment都至少有一個而且只有一個master free list(當然是在非自動段空間管理型別下)。
flg(flag)表示該freelist是否被使用
lhd(list header)表示位於該list中的第一個可用block的dba(Data block address)
ltl(list tail)表示位於該list中的最後一個可用block的dba,這個block必定位於HWM之下。
此時我們可以發現freelists只是記錄了這個segment中空閒塊的第一個塊地址和最後一個塊地址,在第一個空閒塊的塊頭處(block header)記錄了它之後的下一個空閒塊的地址,而下一個空閒塊又記錄了再下一個空閒塊的地址,由此依次記錄,一直到最後一個空閒塊。Oracle通過這種連結串列的方式實現了freelists對於空閒塊的管理。
 
注意:每次當一個block被加入到free list中時,該block會被放置在free list的連結串列頭部。
 
同樣我們可以dump第一個空閒塊來驗證上面的連結串列說法。
比如在lhd部分記錄的dba是0x01c0000a,這是一個16進位制的數,首先轉化為10進位制,於是得到29360138。然後通過oracle提供的兩個函式將塊地址轉化為可以供我們使用的檔案號和塊號,以便於我們進行dump操作。
 
SQL> select dbms_utility.data_block_address_file(29360138) from dual;
 
DBMS_UTILITY.DATA_BLOCK_ADDRES
------------------------------
                             7
 
SQL> select dbms_utility.data_block_address_block(29360138) from dual;
 
DBMS_UTILITY.DATA_BLOCK_ADDRES
------------------------------
                            10
 
現在我們已經得到第一個空閒塊是7號檔案的10號塊。用前面提到的轉儲命令dump這個塊的內容,我們可以找到下面的內容:
fnx: 0x1c0000b
表示下一個可用的塊地址是0x1c0000b,在我們的例子這個塊正好是可用的最後一個塊(segment header block中的lhd部分),我們可以再次dump這個0x1c0000b塊,同樣檢視轉儲的結果,找到下面的內容:
fnx: 0x0
0x0表示下面沒有可用的空閒塊了,也就是表明這是freelists中的最後一個空閒塊。
 
注意:你們的測試可能得到跟我不一樣的轉儲內容,這是正常的。

相關文章