dmt、lmt、mssm,assm的一點總結!

warehouse發表於2007-12-11

這幾個名詞涉及的內容實在是太多了,盡最大能力總結一下,希望能和大家一起分享!

一下寫不完,會不停的補充、完善!


感覺比講課還累:)
未完,不停的整理,修正,完善當中,歡迎大家拍磚!
[php]
在瞭解dmt和lmt之前,先來簡單的熟悉一下oracle資料庫的邏輯結構,邏輯結構描速起來非常簡單:表空

間是由段(segment)組成的,段是由範圍(extent)組成的,範圍是由連續的(block)組成的。這裡也可以通

過一幅眾所周知的圖來表示:

當在表空間裡建立一個table,index等物件時其實對我們使用者而言稱其為物件,但是從oracle儲存的角

度來說把它稱其為segment。我們都知道oracle最小的讀寫單位是block,但是在為物件分配空間時單位卻

是extent,這樣做的好處其實就是為了提高效率。上面提到段是由範圍組成的,當一個extent被分配給一

個segment時,和segment對應的物件就可以使用空間,我們或許從來都不會關心oracle內部到底是如何標

記這個extnet是屬於哪個segment的甚至也可能不會關心這個extent到底是屬於哪一個datafile的,但是

對oracle而言,這卻是一件非常重要的事情。oracle需要一種機制來跟蹤或者記錄一個資料檔案中extent

的使用、空閒情況。Dmt,lmt就是針對表空間中extent是如何被管理而言的。

1、dmt (dictionary managed tablespace)

從oracle9.2開始,default的tablespace都是lmt的,而且也不支援建立dmt型別的表空間了:

SQL> create tablespace dmt datafile 'E:ORACLEPRODUCT10.2.0ORADATATESTDMT.D

BF' SIZE 3M extent management dictionary;

create tablespace dmt datafile 'E:ORACLEPRODUCT10.2.0ORADATATESTDMT.DBF' S

IZE 3M extent management dictionary

*

第 1 行出現錯誤:

ORA-12913: 無法建立字典管理的表空間

SQL>

除非在建立資料庫時選擇定製把system tablespace的區管理型別改成在字典中管理,否則在system

tablespace型別是local的情況下是不支援建立dmt型別的表空間了。

另外值得一提的是從9.2開始,即使在建立db時指定temp tbs為字典管理的,透過dbca建立時可以指定,

但是建立之後還是發現它是local管理的;使用命令建立時直接會報錯:

SQL> col tablespace_name format a20

SQL> select tablespace_name , contents , extent_management from dba_tablespaces;

TABLESPACE_NAME CONTENTS EXTENT_MANAGEMENT

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

SYSTEM PERMANENT DICTIONARY

UNDOTBS1 UNDO LOCAL

SYSAUX PERMANENT LOCAL

TEMP TEMPORARY LOCAL

USERS PERMANENT LOCAL

DMT PERMANENT DICTIONARY

已選擇6行。

上面查詢顯示system tbs是dictionary

SQL> create temporary tablespace tmp tempfile 'E:ORACLEPRODUCT10.2.0ORADATA

DMTTMP.DBF' SIZE 5M extent management dictionary;

create temporary tablespace tmp tempfile 'E:ORACLEPRODUCT10.2.0ORADATADMTT

MP.DBF' SIZE 5M extent management dictionary

*

ERROR at line 1:

ORA-25139: invalid option for CREATE TEMPORARY TABLESPACE

undo tbs在透過dbca建庫時也不允許指定為dictionary型別,命令方式同樣如此:

SQL> create undo tablespace undotbs2 datafile 'E:ORACLEPRODUCT10.2.0ORADATA

UNDOTBS02.DBF' size 3m extent management dictionary;

create undo tablespace undotbs2 datafile 'E:ORACLEPRODUCT10.2.0ORADATAUNDOT

BS02.DBF' size 3m extent management dictionary

*

ERROR at line 1:

ORA-30024: Invalid specification for CREATE UNDO TABLESPACE

說了半天,到底什麼是lmt,其實非常容易理解,當在tbs上建立segment時,表空間裡相應的資料檔案中

的extent是被使用了還是處於空閒是記錄在兩個資料字典表中(uet$:used extent;fet$:free extent),

也就是說Oracle updates the appropriate tables in the data dictionary whenever an extent is

allocated, or freed for reuse. 需要注意的是查詢這兩個表需要sys使用者。

SQL> create table t(id int) tablespace dmt;

Table created.

SQL> select * from uet$ where segfile#<>1;

SEGFILE# SEGBLOCK# EXT# TS# FILE# BLOCK# LENGTH

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

5 2 0 5 5 2 5

uet$欄位簡要介紹:

SEGFILE# segment header block所在的資料檔案編號,對應dba_segments.header_file

SEGBLOCK# segment header block 編號,對應dba_segments.header_block

EXT# extent編號 對應dba_extents.extent_id
TS# tbs編號 對應v$tablespace.ts#
FILE# extent所在的datafile編號,對應dba_data_file.file_id
BLOCK# extent的起始block編號,對dba_extents.block_id
LENGTH 該extent從block#開始所包含的block的數量,對應dba_extents.blocks

SQL> select * from fet$ ;

TS# FILE# BLOCK# LENGTH

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

0 1 13864 5337

5 5 7 186

fet$ 欄位簡要介紹:

TS# 同上

FILE# 同上

BLOCK# 資料檔案file#上free block開始位置

LENGTH free block的長度,block的數量

在建立dmt tbs時指定的資料檔案大小是3m:

SQL> select 3*1024*1024/16384 from dual;

3*1024*1024/16384
-----------------
192

SQL>

192個block - 從uet$得知的從第二個block開始該extent總共包含5個block(也就是2~6),也就是fet$

中顯示的從第7個block開始的186(192 - 7+1)個free block

這種管理extent的方式存在的嚴重問題就是併發性支援很弱,因為在使用者使用物件的過程中只要涉及到

extent的分配或者回收。oracle內部都會對這兩個表進行修改,物件越大,涉及到的extent數量越多,對

這兩個表修改鎖定( ST (space transaction) lock )的時間就越長。如果併發使用者再要多,這兩個表

上的資源爭奪可想而知。另外在修改uet$和fet$的同時本身也是需要undo和redo的,而佔用的undo和redo

和修改普通表沒有什麼兩樣,因此對undo和redo資源本身也是一個衝擊。oracle也意識到了lmt存在的嚴

重缺陷,於是從9.2開始推出了lmt。

另外在建立dmt時可以設定控制extent變化的storage引數,這些引數對tbs而言本身沒有太多意義,它的

作用在於在tbs中為segmeng分配extent時extent的變化情況:

SQL> create tablespace dmt1 datafile 'E:ORACLEPRODUCT10.2.0ORADATADMTDMT01
.DBF' SIZE 10M default storage(
2 initial 64k
3 next 128k
4 pctincrease 50
5 minextents 1
6 maxextents unlimited
7 )
8 extent management dictionary;

表空間已建立。

SQL> create table t_dmt1(id int) tablespace dmt1;

表已建立。

SQL> COL TABLE_NAME FORMAT A10
SQL> SELECT TABLE_NAME , INITIAL_EXTENT,NEXT_EXTENT,MIN_EXTENTS,MAX_EXTENTS,PCT_
INCREASE FROM DBA_TABLES WHERE TABLE_NAME='T_DMT1';

TABLE_NAME INITIAL_EXTENT NEXT_EXTENT MIN_EXTENTS MAX_EXTENTS PCT_INCREASE
---------- -------------- ----------- ----------- ----------- ------------
T_DMT1 65536 131072 1 2147483645 50

SQL>

我們清楚的看到建立在dmt1表空間上的表t_dmt1完全使用了dmt1上的default storage引數,當然也可以

在建表時在table上指定storage引數,這裡不在贅述,有機會介紹table時在做介紹。

2、lmt (locally managed tablespace)

lmt在記錄extent是否是free還是used是透過在資料檔案開頭的幾個block中透過bit位來記錄的。

資料庫中如果不存在dmt型別的表空間,則uet$和fet$中不在有資訊。

SQL> select count(*) from uet$;

COUNT(*)
----------
0

SQL> select count(*) from fet$;

COUNT(*)
----------
0

SQL>

下面建立一個tbs來測試一下:

SQL> create tablespace lmt datafile 'E:ORACLEPRODUCT10.2.0ORADATATESTlmt.d
bf' size 5m;

表空間已建立。

SQL> drop table t;
drop table t
*
第 1 行出現錯誤:
ORA-00942: 表或檢視不存在


SQL> create table t(id int) tablespace lmt ;

表已建立。
SQL> COL segment_name format a3
SQL> select segment_name , extent_id , file_id , block_id , blocks from dba_exte
nts where segment_name='T' AND owner='SYS';

SEG EXTENT_ID FILE_ID BLOCK_ID BLOCKS
--- ---------- ---------- ---------- ----------
T 0 5 9 8

SQL>

BLOCK_ID=9我們知道oracle是從第9個block開始給使用者使用的,那麼1~8這8個block都是做什麼的?眾所

周知第一個block是datafile header,接下來我們dump 2~8:

摘錄dump部分內容如下:

Start dump data blocks tsn: 14 file#: 5 minblk 2 maxblk 8
buffer tsn: 14 rdba: 0x01400002 (5/2)
scn: 0x0000.0014eff2 seq: 0x02 flg: 0x04 tail: 0xeff21d02
frmt: 0x02 chkval: 0xba0e type: 0x1d=KTFB Bitmapped File Space Header
Hex dump of block: st=0, typ_found=1
Dump of memory from 0x04DC2200 to 0x04DC4200
4DC2200 0000A21D 01400002 0014EFF2 04020000 [......@.........]
4DC2210 0000BA0E 00000005 00000008 00000280 [................]
4DC2220 00000001 00000000 00000000 00000007 [................]
4DC2230 00000280 00000001 0000004E 00000000 [........N.......]
4DC2240 00000000 00000000 00000000 00000000 [................]
4DC2250 00000009 00000008 00000000 00000000 [................]
4DC2260 00000000 00000000 00000000 00000000 [................]
Repeat 504 times
4DC41F0 00000000 00000000 00000000 EFF21D02 [................]
File Space Header Block:
Header Control:
RelFno: 5, Unit: 8, Size: 640, Flag: 1
AutoExtend: NO, Increment: 0, MaxSize: 0
Initial Area: 7, Tail: 640, First: 1, Free: 78
Deallocation scn: 0.0
Header Opcode:
Save: No Pending Op

buffer tsn: 14 rdba: 0x01400003 (5/3)
scn: 0x0000.0014eff2 seq: 0x01 flg: 0x04 tail: 0xeff21e01
frmt: 0x02 chkval: 0x4eba type: 0x1e=KTFB Bitmapped File Space Bitmap
Hex dump of block: st=0, typ_found=1
Dump of memory from 0x04DC2200 to 0x04DC4200
4DC2200 0000A21E 01400003 0014EFF2 04010000 [......@.........]
4DC2210 00004EBA 00000005 00000009 00000000 [.N..............]
4DC2220 00000001 0000F7FF 00000000 00000000 [................]
4DC2230 00000000 00000000 00000001 00000000 [................]
4DC2240 00000000 00000000 00000000 00000000 [................]
Repeat 506 times
4DC41F0 00000000 00000000 00000000 EFF21E01 [................]
File Space Bitmap Block:
BitMap Control:
RelFno: 5, BeginBlock: 9, Flag: 0, First: 1, Free: 63487
0100000000000000 0000000000000000

..................................

其中第二個block "type: 0x1d=KTFB Bitmapped File Space Header以及內容File Space Header Block:
Header Control:
RelFno: 5, Unit: 8, Size: 640, Flag: 1
AutoExtend: NO, Increment: 0, MaxSize: 0
Initial Area: 7, Tail: 640, First: 1, Free: 78 ...."記錄的顯然是資料檔案的資訊,不過感覺這部

分內容為什麼不記錄在第一個block中?

從3~8其型別都是:type: 0x1e=KTFB Bitmapped File Space Bitmap,顯然這6個block是真真代替uet$

和fet$來記錄extent的使用、空閒狀態的,接下來看看是如何記錄的:

第3個block的資訊"01000000.................... "是16進位制數,轉為二進位制有意義的資訊是:0000

0001,

其中只有1個"1"表示的正是1個64k的extent;下面建立一個擁有多個extents的segment看看效果:

SQL> create table tt(id int) storage(initial 2m) tablespace lmt;

表已建立。

SQL> select count(*) from dba_extents where owner='SYS' AND segment_name='TT';

COUNT(*)
----------
2

SQL> alter system dump datafile 5 block 3;

系統已更改。

主要資訊摘錄如下:

0100FFFFFFFF0000

轉為為二進位制:

0000 0001 0000 0000 1111 1111 1111 1111 1111 1111 1111 1111

其中0000 0001代表的就是表t所使用的extent,而後面的32個1代表的就是32個64k的extent,正好是2m,

當然在dba_extents中顯示的是2個extent,而oracle在標記的時候始終是以64k為單位標記的。至此lmt是

如何記錄extent的free 、used想必已經很清楚了。

SQL> select 32*64 from dual;

32*64
----------
2048

SQL>

另外在建立lmt型別的tbs時不再支援default storage這些引數,取而代之是autoallocate以及uniform,

default的是autoallocate,autoallocate分配extent的原則是:

segment<=1m ,以64k為單位分配extent;
segment<=64m ,以1m為單位分配extent;
segment<=1g ,以8m為單位分配extent;
segment>1g ,以64m為單位分配extent.
比dmt時的pctincrease強不到哪兒去,尤其時當segment>1g之後,分配extent對連續空間的請求
是很大的,因此建議當segmeng很大時最好使用unifom。以免造成系統還有很多空閒空間時結果系統還是

報不能擴充套件...錯誤。
system tbs必須是autoallocate。


3、dmt和lmt的相互轉化


4、mssm (manual segment space management)

dmt,lmt是管理segment中的extent的,而mssm和assm是管理extent中的block的。mssm是透過segment

header上的freelist 列表在管理extent上處於hwm(high warter mark)下的那些沒有達到pctfree和曾經

達到過pctfree但是後來由於delete等操作空間又緊縮下降到pctused的那些來自不同extent的block所組

成的(doc:A free list is a list of free data blocks that usually includes blocks existing

in a number of different extents within the segment. Free lists are composed of blocks in

which free space has not yet reached PCTFREE or used space has shrunk below PCTUSED. Specify

the number of process free lists with the FREELISTS parameter. The default value of

FREELISTS is one. The maximum value depends on the data block size.)。使用mssm來管理block時

需要在建立表空間時指定manual segment space management語句:

SQL> create tablespace mssm datafile 'E:ORACLEPRODUCT10.2.0ORADATATESTmssm
.dbf' size 3m segment space management manual;

表空間已建立。

SQL>
需要說明的時不論在dmt還時lmt下都可以使用mssm,而且在dmt下只能使用mssm,而下面要介紹的assm只

在lmt下才支援。

瞭解了mssm的機制之後,使用上具體表現在建立segment時需要說明pctused , freelists, freelist

groups引數,當然如果不設定這些引數系統會使用default值。簡單的做個測試:

SQL> create table t( id int ,name char(1000))
2 storage(
3 freelists 1
4 freelist groups 1
5 )
6 pctfree 50
7 pctused 50
8 tablespace mssm;

表已建立。

SQL>

這裡指定了freelists=1 freelist groups=1 其實他們的default值也都是1,只是給出大家語法而已,另

外pctfree 和pctused的default值是10,40。這個值是個百分數,pctfree 表示block的free空間要保留

blcok大小的pctfree,其目的當然就是避免事後由於update操作造成行遷移。行遷移的內容這裡暫時不會

多講。正常情況下,如果hwm下一個block的使用空間沒有達到block_size*(1-pctfree),那麼這個block始

終是在freelists列表上的,如果使用空間達到了block_size*(1-pctfree),那麼這個block脫離了

freelists列表;如果這個block上的資料後來由於各種操作在縮小以至於小於block_size*pctused了,那

麼這個block又重新回到了freelists列表上,意味著在freelists列表上的block都有空閒空間供我們使用

,如果segment上要儲存資料,oracle優先使用freelists列表上的block,當然append方式插入資料除外

。有關pctfree 和pctused這裡有段話說得很精闢(PCTFREE specifies the percentage of a data

block to be reserved (kept free) for possible updates to rows that already are contained in

that block. After a block becomes full, as determined by PCTFREE, Oracle does not consider

the block is for the insertion of new rows until the percentage of the block being used

falls below the parameter PCTUSED.)
簡單的做個測試:

SQL> insert into t values(1 , 'a');

已建立 1 行。

SQL> insert into t values(2 , 'b');

已建立 1 行。

SQL> insert into t values(3 , 'c');

已建立 1 行。

SQL> insert into t values(4 , 'd');

已建立 1 行。

SQL> commit;

提交完成。

SQL> select id , substr(name , 1 , 1) , rowid from t;

ID SU ROWID
---------- -- ------------------
1 a AAACdCAAGAAAAAKAAA
2 b AAACdCAAGAAAAAKAAB
3 c AAACdCAAGAAAAAKAAC
4 d AAACdCAAGAAAAALAAA

SQL> show parameter db_block_size

NAME TYPE VALUE
------------------------------------ ----------- --------------------
db_block_size integer 8192
SQL> analyze table t compute statistics;

表已分析。

SQL> select num_rows,blocks,empty_blocks, num_freelist_blocks
2 from dba_tables where table_name='T' and owner='SYS';

NUM_ROWS BLOCKS EMPTY_BLOCKS NUM_FREELIST_BLOCKS
---------- ---------- ------------ -------------------
4 2 5 1

SQL> delete from t where id=1;

已刪除 1 行。

SQL> commit;

提交完成。

SQL> analyze table t compute statistics;

表已分析。

SQL> select num_rows,blocks,empty_blocks, num_freelist_blocks
2 from dba_tables where table_name='T' and owner='SYS';

NUM_ROWS BLOCKS EMPTY_BLOCKS NUM_FREELIST_BLOCKS
---------- ---------- ------------ -------------------
3 2 5 2

SQL>

透過上面試驗(看rowid的變化,當然需要了解rowid,這裡篇幅所限,rowid不做介紹,可能以後會專門

介紹rowid)我們清晰的看到一個block上只能存放3條資料,插入第4條時使用了另外一個blcok,對錶分

析之後發現NUM_FREELIST_BLOCKS(該欄位表示freelists上block的數量)=1,說明freelists上只有1個

block,而這個block正是資料id=4所在的block,前3條資料所在block由於使用空間達到了8k*(1-

pctfree)=8k*0.5=4k因此從freelist上脫離了,之後刪除了id=1這條資料之後,這個block上存在2條數

據,其佔用的空間大約就是2k多一點,小於8k*pctused=8k*0.5=4k,因此這個blcok又回到了freelists上

,分析表之後顯示的NUM_FREELIST_BLOCKS=2也正好說明了這一點。

繼續插入資料:

SQL> select id , substr(name , 1 , 1) , rowid from t;

ID SU ROWID
---------- -- ------------------
2 b AAACdCAAGAAAAAKAAB
3 c AAACdCAAGAAAAAKAAC
4 d AAACdCAAGAAAAALAAA

SQL> insert into t values(5 , 'e');

已建立 1 行。

SQL> select id , substr(name , 1 , 1) , rowid from t;

ID SU ROWID
---------- -- ------------------
2 b AAACdCAAGAAAAAKAAB
3 c AAACdCAAGAAAAAKAAC
4 d AAACdCAAGAAAAALAAA
5 e AAACdCAAGAAAAALAAB

SQL> insert into t values(6 , 'f');

已建立 1 行。

SQL> select id , substr(name , 1 , 1) , rowid from t;

ID SU ROWID
---------- -- ------------------
2 b AAACdCAAGAAAAAKAAB
3 c AAACdCAAGAAAAAKAAC
4 d AAACdCAAGAAAAALAAA
5 e AAACdCAAGAAAAALAAB
6 f AAACdCAAGAAAAALAAC

SQL> insert into t values(7 , 'g');

已建立 1 行。

SQL> select id , substr(name , 1 , 1) , rowid from t;

ID SU ROWID
---------- -- ------------------
7 g AAACdCAAGAAAAAKAAA
2 b AAACdCAAGAAAAAKAAB
3 c AAACdCAAGAAAAAKAAC
4 d AAACdCAAGAAAAALAAA
5 e AAACdCAAGAAAAALAAB
6 f AAACdCAAGAAAAALAAC

已選擇6行。

SQL> commit;

提交完成。

我們透過觀察rowid的變化發現oracle優先使用了freelists上的block,並沒有分配新的block。當然也可

以透過analyze之後看hwm之下block的數量也是2來斷定。不過這次發現NUM_FREELIST_BLOCKS這個時候是1

而不是我們期望的0。

SQL> analyze table t compute statistics;

表已分析。

SQL> select num_rows,blocks,empty_blocks, num_freelist_blocks
2 from dba_tables where table_name='T' and owner='SYS';

NUM_ROWS BLOCKS EMPTY_BLOCKS NUM_FREELIST_BLOCKS
---------- ---------- ------------ -------------------
6 2 5 1

繼續插入資料觀察一下發現倒是沒有問題:

SQL> insert into t values(8 , 'h');

已建立 1 行。

SQL> commit;

提交完成。

SQL> analyze table t compute statistics;

表已分析。

SQL> select num_rows,blocks,empty_blocks, num_freelist_blocks
2 from dba_tables where table_name='T' and owner='SYS';

NUM_ROWS BLOCKS EMPTY_BLOCKS NUM_FREELIST_BLOCKS
---------- ---------- ------------ -------------------
7 3 4 1

SQL>

為什麼上面hwm下沒有了free block,而NUM_FREELIST_BLOCKS=1不是0,請看下面的測試:
SQL> select id , substr(name , 1 , 1) , rowid,ROWNUM , dbms_rowid.rowid_block_nu
mber(rowid) block_number from t;

ID SU ROWID ROWNUM BLOCK_NUMBER
---------- -- ------------------ ---------- ------------
7 g AAACdCAAGAAAAAKAAA 1 10
4 d AAACdCAAGAAAAAKAAD 2 10
5 e AAACdCAAGAAAAAKAAE 3 10
4 d AAACdCAAGAAAAALAAA 4 11
5 e AAACdCAAGAAAAALAAB 5 11
6 f AAACdCAAGAAAAALAAC 6 11
8 h AAACdCAAGAAAAAMAAA 7 12
9 i AAACdCAAGAAAAAMAAB 8 12
7 g AAACdCAAGAAAAAMAAC 9 12
6 f AAACdCAAGAAAAANAAA 10 13
8 h AAACdCAAGAAAAANAAB 11 13

ID SU ROWID ROWNUM BLOCK_NUMBER
---------- -- ------------------ ---------- ------------
9 i AAACdCAAGAAAAANAAC 12 13

已選擇12行。

SQL> select num_rows,blocks,empty_blocks, num_freelist_blocks
2 from dba_tables where table_name='T' and owner='SYS';

NUM_ROWS BLOCKS EMPTY_BLOCKS NUM_FREELIST_BLOCKS
---------- ---------- ------------ -------------------
12 4 3 1

SQL> ALTER system dump datafile 6 block 9;

系統已更改。

檢視dump檔案freelists中相關內容發現:“SEG LST:: flg: USED lhd: 0x0180000d ltl: 0x0180000d


freelists上的這個block是13,也就是說block13是最後一個滿了的,最後一個雖然滿了,但是在沒有新

的blck加入到freelists上之前這個block是不會從freelists上消失的。
繼續插入資料:
SQL> insert into t values(10,'j');

已建立 1 行。

SQL> commit;

提交完成。

SQL> analyze table t compute statistics;

表已分析。

SQL> select num_rows,blocks,empty_blocks, num_freelist_blocks
2 from dba_tables where table_name='T' and owner='SYS';

NUM_ROWS BLOCKS EMPTY_BLOCKS NUM_FREELIST_BLOCKS
---------- ---------- ------------ -------------------
13 5 2 1

SQL> ALTER system dump datafile 6 block 9;

系統已更改。
檢視dump內容:“SEG LST:: flg: USED lhd: 0x0180000e ltl: 0x0180000e”
發現這次freelists上的block是為新插入資料分配的14號block,13號block從freelists脫離了,那麼什

麼時候
NUM_FREELIST_BLOCKS=0,當hwm下沒有block時:
SQL> truncate table t;

表被截斷。

SQL> analyze table t compute statistics;

表已分析。

SQL> select num_rows,blocks,empty_blocks, num_freelist_blocks
2 from dba_tables where table_name='T' and owner='SYS';

NUM_ROWS BLOCKS EMPTY_BLOCKS NUM_FREELIST_BLOCKS
---------- ---------- ------------ -------------------
0 0 7 0

SQL>

mssm就是這樣一種機制來管理block的空閒和使用情況的,這種方式管理block存在的缺陷主要就是當併發

使用者針對同一個segment請求空間比較多時,會在segment header上的freelists上爭奪激烈,具體tom給

出的引水機的例子非常貼切,大家可以檢視tom的力作。

有關freelists , freelist groups的深入瞭解也可以看以下幾位大師的精彩討論:
[url]http://tech.it168.com/o/2006-04-11/200604112314992.shtml[/url]

5、assm (automatic segment space management)

在介紹mssm時提到mssm主要是對併發性的支援不是很好,如果併發使用者同時在同一個segment上請求空間

時在segment header會發生對freelists列表的爭奪,基於此在lmt下oracle建議我們使用assm,看看

oracle doc是如何來解釋assm的:

This keyword tells Oracle that you want to use bitmaps to manage the free space within

segments. A bitmap, in this case, is a map that describes the status of each data block

within a segment with respect to the amount of space in the block available for inserting

rows. As more or less space becomes available in a data block, its new state is reflected in

the bitmap. Bitmaps enable Oracle to manage free space more automatically; thus, this form

of space management is called automatic segment-space management.

Locally managed tablespaces using automatic segment-space management can be created as

smallfile (traditional) or bigfile tablespaces. AUTO is the default.

以上doc是來之10.2,最後提到AUTO is the default.這是指10g的情況,在9i下manual是default的,下

面看一下如何建立assm模式下的表空間:

SQL> create tablespace assm datafile 'E:oracleproduct10.2.0oradatatestassm
.dbf' size 5m extent management local segment space manageme
nt auto;

表空間已建立。
SQL> select tablespace_name , extent_management , segment_space_management from
dba_tablespaces ;

TABLESPACE_NAME EXTENT_MAN SEGMEN
------------------------------ ---------- ------
SYSTEM LOCAL MANUAL
UNDOTBS1 LOCAL MANUAL
SYSAUX LOCAL AUTO
TEMP LOCAL MANUAL
ASSM LOCAL AUTO

SQL>

在建立表空間assm的語法中其實可以省略"extent management local segment space manageme
nt auto",因為在10g下default的就是lmt下assm型別的。

下面來看看assm內部到底是如何透過block來實現利用bitmap管理segment上block的空閒和使用情況的。

測試如下:

SQL> create table tt tablespace assm as select * from dba_objects;

表已建立。

SQL> select EXTENT_ID , FILE_ID , BLOCK_ID , BLOCKS from dba_extents where segme
nt_name='TT';

EXTENT_ID FILE_ID BLOCK_ID BLOCKS
---------- ---------- ---------- ----------
0 7 9 8
1 7 17 8
2 7 25 8
3 7 33 8
4 7 41 8
5 7 49 8
6 7 57 8
7 7 65 8
8 7 73 8
9 7 81 8
10 7 89 8
11 7 97 8
12 7 105 8
13 7 113 8
14 7 121 8
15 7 129 8
16 7 137 128

已選擇17行。

SQL> select header_file,header_block,blocks,extents from dba_segments where segm
ent_name='TT';

HEADER_FILE HEADER_BLOCK BLOCKS EXTENTS
----------- ------------ ---------- ----------
7 11 256 17

SQL>

HEADER_BLOCK 顯示的是11(segment header),而extent_id=0也就是說第一個extent是從第9個block開

始的,那麼9,10block到底做什麼用了,dump下看看:

SQL> alter system dump datafile 7 block min 9 block max 11;

系統已更改。

dump主要內容摘錄如下:

--===================================

Start dump data blocks tsn: 15 file#: 7 minblk 9 maxblk 11
buffer tsn: 15 rdba: 0x01c00009 (7/9)
scn: 0x0000.001607e3 seq: 0x03 flg: 0x04 tail: 0x07e32003
frmt: 0x02 chkval: 0xa169 type: 0x20=FIRST LEVEL BITMAP BLOCK
Hex dump of block: st=0, typ_found=1
Dump of memory from 0x07082200 to 0x07084200
...........
Dump of First Level Bitmap Block
--------------------------------
nbits : 4 nranges: 2 parent dba: 0x01c0000a poffset: 0
unformatted: 0 total: 16 first useful block: 3
owning instance : 1
instance ownership changed at
Last successful Search
Freeness Status: nf1 0 nf2 0 nf3 0 nf4 0

Extent Map Block Offset: 4294967295
First free datablock : 16
Bitmap block lock opcode 0
Locker xid: : 0x0000.000.00000000
Inc #: 0 Objd: 10056
--------------------------------------------------------
DBA Ranges :
--------------------------------------------------------
0x01c00009 Length: 8 Offset: 0
0x01c00011 Length: 8 Offset: 8

0:Metadata 1:Metadata 2:Metadata 3:FULL
4:FULL 5:FULL 6:FULL 7:FULL
8:FULL 9:FULL 10:FULL 11:FULL
12:FULL 13:FULL 14:FULL 15:FULL
--------------------------------------------------------
buffer tsn: 15 rdba: 0x01c0000a (7/10)
scn: 0x0000.001607e3 seq: 0x09 flg: 0x04 tail: 0x07e32109
frmt: 0x02 chkval: 0xa07c type: 0x21=SECOND LEVEL BITMAP BLOCK
Hex dump of block: st=0, typ_found=1
Dump of memory from 0x07082200 to 0x07084200
.................
Dump of Second Level Bitmap Block
number: 10 nfree: 2 ffree: 8 pdba: 0x01c0000b
Inc #: 0 Objd: 10056
opcode:0
xid:
L1 Ranges :
--------------------------------------------------------
0x01c00009 Free: 1 Inst: 1
0x01c00019 Free: 1 Inst: 1
0x01c00029 Free: 1 Inst: 1
0x01c00039 Free: 1 Inst: 1
0x01c00049 Free: 1 Inst: 1
0x01c00059 Free: 1 Inst: 1
0x01c00069 Free: 1 Inst: 1
0x01c00079 Free: 1 Inst: 1
0x01c00089 Free: 5 Inst: 1
0x01c0008a Free: 5 Inst: 1

--------------------------------------------------------
buffer tsn: 15 rdba: 0x01c0000b (7/11)
scn: 0x0000.001607e5 seq: 0x01 flg: 0x04 tail: 0x07e52301
frmt: 0x02 chkval: 0x8d53 type: 0x23=PAGETABLE SEGMENT HEADER
Hex dump of block: st=0, typ_found=1
Dump of memory from 0x07082200 to 0x07084200
.............
Extent Control Header
-----------------------------------------------------------------
Extent Header:: spare1: 0 spare2: 0 #extents: 17 #blocks: 256
last map 0x00000000 #maps: 0 offset: 2716
Highwater:: 0x01c0008c ext#: 16 blk#: 3 ext size: 128
#blocks in seg. hdr's freelists: 0
#blocks below: 131
mapblk 0x00000000 offset: 16
Unlocked
--------------------------------------------------------
Low HighWater Mark :
Highwater:: 0x01c0008c ext#: 16 blk#: 3 ext size: 128
#blocks in seg. hdr's freelists: 0
#blocks below: 131
mapblk 0x00000000 offset: 16
Level 1 BMB for High HWM block: 0x01c00089
Level 1 BMB for Low HWM block: 0x01c00089
--------------------------------------------------------
Segment Type: 1 nl2: 1 blksz: 8192 fbsz: 0
L2 Array start offset: 0x00001434
First Level 3 BMB: 0x00000000
L2 Hint for inserts: 0x01c0000a
Last Level 1 BMB: 0x01c0008a
Last Level II BMB: 0x01c0000a
Last Level III BMB: 0x00000000
Map Header:: next 0x00000000 #extents: 17 obj#: 10056 flag: 0x10000000
Inc # 0
Extent Map
-----------------------------------------------------------------
0x01c00009 length: 8
0x01c00011 length: 8
0x01c00019 length: 8
0x01c00021 length: 8
0x01c00029 length: 8
0x01c00031 length: 8
0x01c00039 length: 8
0x01c00041 length: 8
0x01c00049 length: 8
0x01c00051 length: 8
0x01c00059 length: 8
0x01c00061 length: 8
0x01c00069 length: 8
0x01c00071 length: 8
0x01c00079 length: 8
0x01c00081 length: 8
0x01c00089 length: 128

Auxillary Map
--------------------------------------------------------
Extent 0 : L1 dba: 0x01c00009 Data dba: 0x01c0000c
Extent 1 : L1 dba: 0x01c00009 Data dba: 0x01c00011
Extent 2 : L1 dba: 0x01c00019 Data dba: 0x01c0001a
Extent 3 : L1 dba: 0x01c00019 Data dba: 0x01c00021
Extent 4 : L1 dba: 0x01c00029 Data dba: 0x01c0002a
Extent 5 : L1 dba: 0x01c00029 Data dba: 0x01c00031
Extent 6 : L1 dba: 0x01c00039 Data dba: 0x01c0003a
Extent 7 : L1 dba: 0x01c00039 Data dba: 0x01c00041
Extent 8 : L1 dba: 0x01c00049 Data dba: 0x01c0004a
Extent 9 : L1 dba: 0x01c00049 Data dba: 0x01c00051
Extent 10 : L1 dba: 0x01c00059 Data dba: 0x01c0005a
Extent 11 : L1 dba: 0x01c00059 Data dba: 0x01c00061
Extent 12 : L1 dba: 0x01c00069 Data dba: 0x01c0006a
Extent 13 : L1 dba: 0x01c00069 Data dba: 0x01c00071
Extent 14 : L1 dba: 0x01c00079 Data dba: 0x01c0007a
Extent 15 : L1 dba: 0x01c00079 Data dba: 0x01c00081
Extent 16 : L1 dba: 0x01c00089 Data dba: 0x01c0008b
--------------------------------------------------------

Second Level Bitmap block DBAs
--------------------------------------------------------
DBA 1: 0x01c0000a

End dump data blocks tsn: 15 file#: 7 minblk 9 maxblk 11

--===================================

其中在第9個block的dump資訊中我們發現type: 0x20=FIRST LEVEL BITMAP BLOCK,說明這個block是第一

級bitmap block,oracle用第一級bitmap block來管理data block的使用情況:

--------------------------------------------------------
DBA Ranges :
--------------------------------------------------------
0x01c00009 Length: 8 Offset: 0
0x01c00011 Length: 8 Offset: 8

0:Metadata 1:Metadata 2:Metadata 3:FULL
4:FULL 5:FULL 6:FULL 7:FULL
8:FULL 9:FULL 10:FULL 11:FULL
12:FULL 13:FULL 14:FULL 15:FULL
--------------------------------------------------------
從上面內容(來自block 9的dump)發現9#block總共管理了16個block,也就是2個extent。由於extent

是由連續的block組成的,因此只需要記錄每個extent的起始block地址(0x01c00009)和extent的數量即可

兩個16進位制的dba轉化為10進位制的分別是:

SQL> select dbms_utility.data_block_address_block(to_number('01c00009','xxxxxxxx
')) from dual;

DBMS_UTILITY.DATA_BLOCK_ADDRESS_BLOCK(TO_NUMBER('01C00009','XXXXXXXX'))
-----------------------------------------------------------------------
9
SQL> select dbms_utility.data_block_address_block(to_number('01c000011','xxxxxxx
xx')) from dual;

DBMS_UTILITY.DATA_BLOCK_ADDRESS_BLOCK(TO_NUMBER('01C000011','XXXXXXXXX'))
-------------------------------------------------------------------------
17

SQL>

而block 9,17不正是我們上面查詢dba_extents是顯示的extent_id = 0 , 1兩個extent

另外9# block dump資訊中的:

0:Metadata 1:Metadata 2:Metadata

表示9#~11#block顯示的是Metadata(後設資料:資料倉儲中非常重要的概念,管理資料的資料,oracle中

的資料字典據都可以理解成後設資料),其中0表示是9#block,1 表示10#block,2 表示11#block

(segment header),其他顯示的都是full,表示這些block上都已經沒有可用的空閒空間。同時也發現

我們真真使用資料是從12#block開始的。

9#block dump內容裡還有一個重要的資訊就是parent dba: 0x01c0000a表示9#block的parent block

的地址,而這個block的地址正好是10#block的地址:rdba: 0x01c0000a。

至此9#block暫時分析完畢。

--==================================

再來10#block:

10#block的型別是:type: 0x21=SECOND LEVEL BITMAP BLOCK

說明該block是二級bitmap block,他是用來管理一級bitmap block的。

10#block的主要dump資訊:

L1 Ranges :
--------------------------------------------------------
0x01c00009 Free: 1 Inst: 1
0x01c00019 Free: 1 Inst: 1
0x01c00029 Free: 1 Inst: 1
0x01c00039 Free: 1 Inst: 1
0x01c00049 Free: 1 Inst: 1
0x01c00059 Free: 1 Inst: 1
0x01c00069 Free: 1 Inst: 1
0x01c00079 Free: 1 Inst: 1
0x01c00089 Free: 5 Inst: 1
0x01c0008a Free: 5 Inst: 1

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

其中L1 Ranges 中的哪些dba轉為10進位制如下:
9
25
41
57
73
89
105
121
137
138

而這些值都是一級bitmap block的block_id,而這些值不正是dba_extents中顯示的,同時也看到每一個一

級bitmap block管理了16個data block。不過奇怪的是為什麼138#block怎麼也成了一級bitmap block了

?暫時解釋不清。

SQL> select block_id from dba_extents where segment_name='TT' AND mod(extent_id,
2)=0;

BLOCK_ID
----------
9
25
41
57
73
89
105
121
137

已選擇9行。

SQL>

再來看看10#block的 pdba: 0x01c0000b,這個地址正是11#block的dba:rdba: 0x01c0000b 。

接下來簡單看看11#block的型別是:

type: 0x23=PAGETABLE SEGMENT HEADER

也就是我們熟悉的segment header block,這裡它也同時是一個特殊的三級bitmap block

同時最下面一條非常有用的資訊是:

Second Level Bitmap block DBAs
--------------------------------------------------------
DBA 1: 0x01c0000a

記錄了二級btimap block的地址,因為segment小,只有1個二級bitmap block,大家也可以建立一個大一

點的表,主要需要保證要有足夠多的block才可能看到第二個二級block出現,要看到出現一個三級bitmap

block可能非常的難。

感興趣的話大家也可以參考eygle,piner兩位版主的力作:


http://www.itpub.net/thread-734505-1-3.html

.
[/php]

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/19602/viewspace-61756/,如需轉載,請註明出處,否則將追究法律責任。

相關文章