Freelists和Freelist Groups
- 格式:docx
- 大小:202.56 KB
- 文档页数:14
刚才Debbie问什么是freelists,我直接copy老盖的文章了,不过发现竟然是张乐奕写的!也是一个大牛啊,不过被老盖收到自己麾下了。
N多大牛被老盖收了,不得不说这是老盖超越众多更牛DBA比较IN的地方。
一.什么是freelists本文在于探讨Freelists和Freelist Groups的作用,存取机制,争用诊断和优化方法,同时通过理论和测试来推翻一些存在了很久的错误观点。
本文的读者应该具有较深入的Oracle知识,对于一般的开发人员这篇文章可能并没有太多的帮助。
我们知道Oracle数据库的读取单位是数据块(Block),而一个Block是否允许被写入数据是基于一定的空闲度,这就是大家知道的pctfree和pctused存储参数设置。
假设pctfree=10, pctused=40,这就表明当一个Block的空间使用率达到了90%(100-pctfree)时,这个block就不再允许被用于新增数据(insert),而保留下来的这10%的空间则被预留为行更新(update)所可能需要的空间扩展,我们说此时这个block就从freelist上被摘走了(实际上还有另外一种情况,就是当块剩余空间不足以插入一条记录并且该块的使用率已经超过了pctused定义的值并且该块位于freelist header处时,该块也会从freelist上被摘走,术语称为UNLINK)。
当有数据删除(delete)的时候,只有该block中的数据被删除到一定的程度,该块才会重新被加入到freelists中,而这个程度就是pctused参数定义的数值,如我们这个例子中,只有块中的数据降低到40%以下的时候,该块才被重新允许用于新增数据。
通过上面的描述,可以知道所谓freelists,就是一个指定了所有可以用于insert操作的数据块的列表。
存在在这个列表中的数据块才能用于insert操作,一旦一个数据块无法用于insert(达到了pctfree参数指定的限度)则立刻从这个列表中被摘除。
freelists的作用就在于管理高水位标志(HWM)以下的空闲空间。
注意:freelists只是管理高水位标志以下的空闲空间,而实际上一个segment可用的空闲空间包括两种类型:1.已经分配给这个segment但是从来未被使用过的位于高水位标志之上的blocks2.位于高水位标志之下,被链接在freelists上的blocks至于freelist groups的概念和作用,在下面的章节适当的地方会解释。
二.freelists是否已经过时随着Oracle9i的推出,对于空闲块的管理变得更加智能和有效率了。
在LMT(Locally Managed Tablespaces)中如果指定了ASSM(Automatic Segment Space Management),那么对于任何pctused,freelists,freelist groups存储参数的指定都将被忽略。
创建ASSM表空间的方法如下:CREATE TABLESPACE lmtbsb DATAFILE '/u02/oracle/data/lmtbsb01.dbf' SIZE 50MEXTENT MANAGEMENT LOCALSEGMENT SPACE MANAGEMENT AUTO;ASSM得益于使用位图(bitmaps)来管理段中的空闲块,至于具体是如何管理的,那又是另外一篇文章了。
就此意义上来说,对于freelists的探讨确实可能已经有些过时了,但是首先并不是所有的数据库现在都已经升级到了Oracle9i,甚至在最需要调整的一些大型应用上往往都由于业务的稳定性而不愿意冒升级到新版本的危险;其次即使是新的应用使用了Oracle9i数据库,如果数据库管理员在创建表空间的时候没有明确指定SEGMENT SPACE MANAGEMENT AUTO,那么默认情况下仍然会使用Freelists和Freelist Groups来管理Free Block。
所以,在仍然存在有大量Oracle8i数据库和非自动段空间管理表空间的现在,对于freelists的研究仍然具有很实际的意义,而由于默认的freelists和freelist groups又都只有1,所以又恰恰是高负载的应用中最需要调整(Tuning)的部分之一。
三.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 1T_MANUAL_FREE2 TABLE 2 1T_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------------------------------7SQL> 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: 0x00x0表示下面没有可用的空闲块了,也就是表明这是freelists中的最后一个空闲块。
注意:你们的测试可能得到跟我不一样的转储内容,这是正常的。
一.有多少种free list1.master free list或者segment free list简称为MFL,在segment被创建的时候自动生成的,如果我们在创建segment时没有指定freelists参数,或者指定freelists=1,都是生成这个MFL。
MFL对于每个segment来说有且只有一个(如果指定freelists>1,产生的就是不是MFL,这一点将在process free list部分解释)。