在Oracle数据库内部,对象空间是以段的形式(Segment)存在和管理的,通过不同的段类型Oracle将段区分开来,在Oracle 9i中,主要的段类型有:
SQL> select distinct(segment_type) from dba_segments; SEGMENT_TYPE ------------------ CACHE CLUSTER INDEX INDEX PARTITION LOBINDEX LOBSEGMENT NESTED TABLE ROLLBACK TABLE TABLE PARTITION TYPE2 UNDO 11 rows selected.
当一个段被创建时,区间(Extent)就被分配,随着后续的不断使用,一个段的空间可以以区为单位不断扩展。
前面提到Extent的管理技术是通过字典或本地的方式进行的,那么当Extent被分配给Segment,这个空间又是如何管理的呢?“SEGMENT SPACE MANAGEMENT AUTO”这个语句就是定义的段空间管理方式。
Oracle的段空间管理方式主要有两种,一种是手工段空间管理(Manual Segment Space Management,缩写为MSSM),由于这种方式使用自由列表来管理段空间,所以也被称为自由列表管理方式(Freelist Mangement,缩写为FLM),一种就是Oracle 9i带来的全新的自动段空间管理(Auto Segment Space Management,缩写为ASSM)。
手工段空间管理(Manual Segment Space Management)
MSSM管理方式是Oracle最初实现的一种段空间管理技术。前面提到,区间(Extent)是Oracle的最小空间分配单元,而Block是Oracle的最小IO操作单元,也就是说,Oracle以区间为单位将空间分配给对象段,而段内则是以Block为单位进行空间使用和管理的。
这个段空间管理在Oracle 9i之前是通过手工段空间管理技术实现的,这种技术的具体实现方式是通过在段头(Segment Header)分配自由列表(freelist)来管理Block的使用,简单一点,可以把自由列表想象成一个数据表,Oracle依赖一系列的算法通过向自由列表中加入或移出Block来实现段空间管理。
当创建对象时(如数据表)可以定义freelist的数量,对于数据表缺省的freelist为1,可以通过dba_segments查询得到这些数据:
SQL> select SEGMENT_NAME,SEGMENT_TYPE,FREELISTS,FREELIST_GROUPS 2 from DBA_SEGMENTS where TABLESPACE_NAME='EYGLE'; SEGMENT_NA SEGMENT_TYPE FREELISTS FREELIST_GROUPS ---------- ------------------ ---------- --------------- TEST TABLE 1 1 TEST3 TABLE 1 1
当向一个对象中插入数据时,Oracle首先在该对象的freelist上寻找可用于插入数据的Block,当一个Block用完之后,就会从freelist上摘除,当这个Block上由于数据删除等空间释放后,可以再次回到freelist上来,而这主要是通过存储参数PCTFREE和PCTUSED来实现。
当向一个对象中插入数据时,假设PCTFREE=20,PCTUSED=40,这就表明当一个Block的空间使用率达到了80%时,这个block就不再允许被用于新增数据(insert),而保留下来的这20%的空间则被预留为行更新(update)所可能需要的空间扩展,此时这个Block就从freelist上被移除;当这个Block中有数据被删除(delete)时,空间不断被释放,当空间使用低于PCTUSED参数设置时(此处即为40%),这个数据块块才会重新被加入到freelists中,加入freelist后这个Block又可以被插入新的数据,如图5-3所示。
图5-3 数据库空间的使用
通过以上的描述可以看到,如果一个段的操作非常频繁,那么很多用户就会同时请求访问freelist,并对freelist进行修改,这就很容易产生竞争。对于表来说,缺省的freelist为1,这就很容易引发竞争,虽然可以通过增加freelist的方法缓解这种竞争,但是我们已经看到这种管理方式存在的缺陷。所以从Oracle 9i开始,Oracle推出了ASSM的管理方式。
接下来可以通过DUMP的方式来转储数据块的头信息,发现freelist的设置等:
SQL> select segment_name,file_id,block_id,blocks 2 from dba_extents where tablespace_name='EYGLE'; SEGMENT_NA FILE_ID BLOCK_ID BLOCKS ---------- ---------- ---------- ---------- TEST 3 9 128 TEST 3 137 128 TEST3 3 777 128 SQL> alter system dump datafile 3 block 9; System altered.
检查trace文件就可以发现如下信息:
buffer tsn: 4 rdba: 0x00c00009 (3/9) scn: 0x0004.6c1e9774 seq: 0x01 flg: 0x00 tail: 0x97741001 frmt: 0x02 chkval: 0x0000 type: 0x10=DATA SEGMENT HEADER - UNLIMITED Extent Control Header ----------------------------------------------------------------- Extent Header:: spare1: 0 spare2: 0 #extents: 2 #blocks: 255 last map 0x00000000 #maps: 0 offset: 4128 Highwater:: 0x00c00056 ext#: 0 blk#: 76 ext size: 127 #blocks in seg. hdr's freelists: 76 #blocks below: 76 mapblk 0x00000000 offset: 0 Unlocked Map Header:: next 0x00000000 #extents: 2 obj#: 9969 flag: 0x40000000 Extent Map ----------------------------------------------------------------- 0x00c0000a length: 127 0x00c00089 length: 128 nfl = 1, nfb = 1 typ = 1 nxf = 1 ccnt = 0 SEG LST:: flg: UNUSED lhd: 0x00000000 ltl: 0x00000000 XCT LST:: flg: USED lhd: 0x00c00055 ltl: 0x00c0000a xid: 0x0001.008.00000256 End dump data blocks tsn: 4 file#: 3 minblk 9 maxblk 9
这里的hdr's freelists就是指freelist里面的数据块数量,本例的表中,freelist中有76个空闲数据块。有兴趣的读者可以进行一点深入研究,这里不再过多介绍