分析以及测试在一个segment中freelists以及HWM的变化情况(2)

 
freelists=2以及freelistgroups=1的表对freelist, freelistgroups以及HWM分析之前,先了解freelists种类以及freelstgroups的定义:
freelistgroups定义:即多个freelists的集合
freelists类如下:
master free list:也叫segment free list,如果在创建segment时没有定义freelists默认是freelists=1,freelistroups=1,MFL相当于共享空间池,当有多个进程同时插入时,就有可能出现多个对MFL的争用;如果出现这种现象,则可以通过定义freelistgroups参数来设置多个freelists从而设置了多个MFL.来缓解对MFL的争用;
process free list:是主要用于进程的freelists.当freelists参数设置大于1,假设设置为freelists=3,则表示当有多个进程同时进行插入操作时,则可以允许3个进程并发进行插入操作,是进程级别上的freelist;
transaction free list:每个进程会有自己的PFL每个进程内的进行的每个事务也有专用的一个freelist,是事务级别上的freelist;
super master free list:也叫segment master free list,当有多个freelistgroups时,才会有SFL的存在,主要是用来缓解对HWM调整权的争用;
 
在上一篇笔记中,我创建了表T_MANUAL_free2,其中的freelists=2, freelist groups=1,下面主要用这张表来分析PFL以及TFL的变化情况
测试1:freelists是如何开始使用的?
在未插入数据之前表的segment信息:
begin
show_space('T_MANUAL_FREE2');
end;
Free Blocks.............................0
l_free_blks0
Total Blocks............................8
Total Bytes.............................65536
Unused Blocks...........................7
Unused Bytes............................57344
Last Used Ext FileId....................11
Last Used Ext BlockId...................17
Last Used Block.........................1
0on FREELIST,0used by table
 
alter system dump datafile 11 block 17
 
此时的segment 信息如下:
*** 2008-03-29 16:58:48.268
 Extent Control Header
 -----------------------------------------------------------------
 Extent Header:: spare1: 0       spare2: 0      #extents: 1      #blocks: 7
                  last map 0x00000000 #maps: 0      offset: 4128
      Highwater:: 0x02c00012  ext#: 0      blk#: 0      ext size: 7
  #blocks in seg. hdr's freelists: 0 --freelist 链表中没有空闲数据块
 #blocks below: 0             --HWM 标志下没有数据块
 mapblk 0x00000000 offset: 0
                   Unlocked
     Map Header:: next 0x00000000 #extents: 1    obj#: 32108 flag: 0x40000000
 Extent Map
 -----------------------------------------------------------------
   0x02c00012 length: 7
 nfl = 2, nfb = 1 typ = 1 nxf = 0 ccnt = 0
  SEG LST:: flg: UNUSED lhd: 0x00000000 ltl: 0x00000000
 SEG LST:: flg: UNUSED lhd: 0x00000000 ltl: 0x00000000
 SEG LST:: flg: UNUSED lhd: 0x00000000 ltl: 0x00000000
End dump data blocks tsn: 13 file#: 11 minblk 17 maxblk 17
分析:红色标识的地方,是 freelists的一些信息,可以看出有该segment有三个freelists,1个是MFL,有2个PFL,在还没有数据插入时,它们都处于unused状态;,因为此时HWM标志下还没有数据块,也就不会有空闲的数据块放到freelist中,各个freelist链表中也没有数据块
 
下面设置表T_MANUAL_free2的初始值:
   declare
   a char(1000);
   begin
   a:='aaaa';
   for i in 1..20   loop
  insert into T_MANUAL_FREE2 values(i,a);
   commit;
   end loop;
   end;
 
begin
show_space('T_MANUAL_FREE2');
end;
显示如下:
Free Blocks.............................1
l_free_blks1
Total Blocks............................8
Total Bytes.............................65536
Unused Blocks...........................4
Unused Bytes............................32768
Last Used Ext FileId....................11
Last Used Ext BlockId...................17
Last Used Block.........................4
1on FREELIST,3used by table   
 
SQL> select t.id,dbms_rowid.rowid_object(rowid) data_object_id#,
 2          dbms_rowid.rowid_relative_fno(rowid) rfile#,
 3          dbms_rowid.rowid_block_number(rowid) block#,
 4          dbms_rowid.rowid_row_number(rowid) row#
 5     from T_MANUAL_FREE2 t;
 
        ID DATA_OBJECT_ID#     RFILE#     BLOCK#       ROW#
---------- --------------- ---------- ---------- ----------
         1           32107         11         18          0
         2           32107         11         18          1
         3           32107         11         18          2
         4           32107         11         18          3
         5           32107         11         18          4
         6           32107         11         18          5
         7           32107         11         18          6
         8           32107         11         19          0
         9           32107         11         19          1
        10           32107         11         19          2
        11           32107         11         19          3
        12           32107         11         19          4
        13           32107         11         19          5
        14           32107         11         19          6
        15           32107         11         20          0
        16           32107         11         20          1
        17           32107         11         20          2
        18           32107         11         20          3
        19           32107         11         20          4
        20          32107         11         20          5
20 rows selected
 
插入数据之后的segment header的变化情况:
*** 2008-03-29 17:10:19.993
Start dump data blocks tsn: 13 file#: 11 minblk 17 maxblk 20
buffer tsn: 13 rdba: 0x02c00011 (11/17)
scn: 0x0000.00180d66 seq: 0x02 flg: 0x00 tail: 0x0d661002
frmt: 0x02 chkval: 0x0000 type: 0x10=DATA SEGMENT HEADER - UNLIMITED
 Extent Control Header
 -----------------------------------------------------------------
 Extent Header:: spare1: 0       spare2: 0      #extents: 1      #blocks: 7
                  last map 0x00000000 #maps: 0      offset: 4128
      Highwater:: 0x02c00015 ext#: 0      blk#: 3      ext size: 7 - 相比较插入数据前的 HWM, 此时 HWM 已经由原来的 0x02c00012 推移了三个数据块到 0x02c00015
  #blocks in seg. hdr's freelists: 1  -- segment 中的 freelists 链表中只有一个空闲数据块
 #blocks below: 3             -- HWM 标志下有三个数据块
 mapblk 0x00000000 offset: 0
                   Unlocked
     Map Header:: next  0x00000000 #extents: 1    obj#: 32108 flag: 0x40000000
 Extent Map
 -----------------------------------------------------------------
   0x02c00012 length: 7
 
 nfl = 2, nfb = 1 typ = 1 nxf = 0 ccnt = 0
  SEG LST:: flg: UNUSED lhd: 0x00000000 ltl: 0x00000000 -- UNUSED 说明该 freelists 链表已经处于不可用状态 , 因为链表中已经没有空闲数据块 ;
 SEG LST:: flg: UNUSED lhd: 0x00000000 ltl: 0x00000000
   SEG LST:: flg: USED   lhd: 0x02c00014 ltl: 0x02c00014   -- USED 说明该 freelists 链表还在使用中
scn: 0x0000.00180d5a seq: 0x02 flg: 0x00 tail: 0x0d5a0602
frmt: 0x02 chkval: 0x0000 type: 0x06=trans data
Block header dump: 0x02c00012
 Object id on Block? Y
 seg/obj: 0x7d6c csc: 0x00.180d5a itc: 2 flg: - typ: 1 - DATA
     fsl: 0 fnx: 0x0 ver: 0x01
 Itl            Xid                  Uba         Flag Lck        Scn/Fsc
0x01    0x0006.017.000004fa 0x00801863.005a.0a C---    0 scn 0x0000.00180d59
0x02    0x0005.025.0000054b 0x00800266.0056.0e C---    0 scn 0x0000.00180d57
 
End dump data blocks tsn: 13 file#: 11 minblk 17 maxblk 17
分析:根据 SEG LST:: flg: USED   lhd: 0x02c00014 ltl: 0x02c00014,说明该链表的开始的数据块的地址为0x02c00014,转换为10进制,得到46137364,则计算该freelist链表所用的文件及块
为:
SQL> select dbms_utility.data_block_address_file(46137364) from dual;
DBMS_UTILITY.DATA_BLOCK_ADDRES
------------------------------
            11
SQL> select dbms_utility.data_block_address_block(46137364) from dual;
DBMS_UTILITY.DATA_BLOCK_ADDRES
------------------------------
            20
说明该freelist链表中唯一的一个数据块是文件11数据块20.
 
测试2:事务是如何影响TFL的产生的?
下面先删除一部分数据,先不提交,查看下segment header上的信息,然后提交之后,再查看下segment header上的信息,进行比较
:删除数据,但是先不提交,使得数据块20的所用空间低于PCTUSED所设定的限制,然后查看block中的一些参数的变化:
begin
delete from T_MANUAL_FREE2 t
where t.id between 2 and 6 ;
end;
上面的删除操作事务没有提交,这个时候segment header信息如下:
Start dump data blocks tsn: 13 file#: 11 minblk 17 maxblk 21
buffer tsn: 13 rdba: 0x02c00011 (11/17)
scn: 0x0000.00181945 seq: 0x01 flg: 0x00 tail: 0x19451001
frmt: 0x02 chkval: 0x0000 type: 0x10=DATA SEGMENT HEADER - UNLIMITED
 Extent Control Header
 -----------------------------------------------------------------
 Extent Header:: spare1: 0       spare2: 0      #extents: 1      #blocks: 7
                  last map 0x00000000 #maps: 0      offset: 4128
      Highwater:: 0x02c00015 ext#: 0      blk#: 3      ext size: 7
 #blocks in seg. hdr's freelists: 1
 #blocks below: 3
 mapblk 0x00000000 offset: 0
                   Unlocked
     Map Header:: next 0x00000000 #extents: 1    obj#: 32110 flag: 0x40000000
 Extent Map
 -----------------------------------------------------------------
  0x02c00012 length: 7
 
 nfl = 2, nfb = 1 typ = 1 nxf = 1 ccnt = 0
 SEG LST:: flg: UNUSED lhd: 0x00000000 ltl: 0x00000000
 SEG LST:: flg: UNUSED lhd: 0x00000000 ltl: 0x00000000
   SEG LST:: flg: USED   lhd: 0x02c00014 ltl: 0x02c00014
 XCT LST:: flg: USED   lhd: 0x00000000 ltl: 0x00000000 xid: 0x0003.021.00000531 -- 自动产生一个 TFL, xid: 0x0003.021.00000531 表示 transaction ID
buffer tsn: 13 rdba: 0x02c00012 (11/18)
scn: 0x0000.00181945 seq: 0x06 flg: 0x00 tail: 0x19450606
frmt: 0x02 chkval: 0x0000 type: 0x06=trans data
Block header dump: 0x02c00012
 Object id on Block? Y
 seg/obj: 0x7d6e csc: 0x00.181923 itc: 2 flg: - typ: 1 - DATA
     fsl: 0 fnx: 0x0 ver: 0x01
 
 Itl            Xid                  Uba         Flag Lck        Scn/Fsc
0x01    0x0008.021.0000055f 0x00800668.005b.29 C---    0 scn 0x0000.00181923
0x02    0x0003.021.00000531 0x00800a70.00ba.16 ----   10 fsc 0x0000.00000000
分析:由于删除数据的事务没有提交,此时oracle会根据需要自动产生一个TFL,每个segment最少可以有16个TFL除非达到segment header block size的大小,当没有空间允许新的事务得到自己的TFL时,此时这个事务需要等待其他的事务提交并释放TFL.
 
提交这个事务之后,segment header的信息变化为:
Start dump data blocks tsn: 13 file#: 11 minblk 17 maxblk 21
buffer tsn: 13 rdba: 0x02c00011 (11/17)
scn: 0x0000.00181dda seq: 0x01 flg: 0x00 tail: 0x1dda1001
frmt: 0x02 chkval: 0x0000 type: 0x10=DATA SEGMENT HEADER - UNLIMITED
 Extent Control Header
 -----------------------------------------------------------------
 Extent Header:: spare1: 0       spare2: 0      #extents: 1      #blocks: 7    
                  last map 0x00000000 #maps: 0      offset: 4128 
      Highwater:: 0x02c00015 ext#: 0      blk#: 3      ext size: 7    
  #blocks in seg. hdr's freelists: 2     --freelist 链表上的数据块的个数增加了一个数据块 , 是由于删除数据使得一个数据块的所用的空间低于 PCTUSED 所设置的限制 , 所以该数据块 link freelist 链表中
 #blocks below: 3     
 mapblk 0x00000000 offset: 0     
                   Unlocked
     Map Header:: next 0x00000000 #extents: 1    obj#: 32112 flag: 0x40000000
 Extent Map
 -----------------------------------------------------------------
   0x02c00012 length: 7    
 
 nfl = 2, nfb = 1 typ = 1 nxf = 1 ccnt = 1
  SEG LST:: flg: USED   lhd: 0x02c00012 ltl: 0x02c00012 新的 PFL 投入使用 , freelist 链表的初始位置通过计算是在 18 数据块
 SEG LST:: flg: UNUSED lhd: 0x00000000 ltl: 0x00000000
 SEG LST:: flg: USED    lhd: 0x02c00014 ltl: 0x02c00014
  XCT LST:: flg: UNUSED lhd: 0x00000000 ltl: 0x00000000 xid: 0x0000.000.00000000 事务已经被释放 , 所以自动产生的 TFL transcation ID 0
buffer tsn: 13 rdba: 0x02c00012 (11/18)
scn: 0x0000.00181dda seq: 0x01 flg: 0x00 tail: 0x1dda0601
frmt: 0x02 chkval: 0x0000 type: 0x06=trans data
Block header dump: 0x02c00012
 Object id on Block? Y
 seg/obj: 0x7d70 csc: 0x00.181d80 itc: 2 flg: O typ: 1 - DATA
     fsl: 2 fnx: 0x0 ver: 0x01
 Itl            Xid                  Uba         Flag Lck        Scn/Fsc
0x01    0x0001.00c.00000547 0x008003f3.0051.02 C---    0 scn 0x0000.00181d80
0x02    0x0007.006.000004a5 0x00800aee.0056.03 --U-    6 fsc 0x13ab.00181dd8
分析:提交之后,由于删除在18数据块上的数据,删除以后使得18数据块的使用空间低于PCTUSED所限制的空间,则该数据块link到freelist链表上,又由于该segment上定义了freelists=2,所以此时一个新的PFL投入使用,则此时该segment上有2个PFL链表.并且原来的TFL的 transaction ID自动清0。
 
测试3:2个进程同时进行,是如何影响PFL,TFL以及MFL链表以及HWM的?
开始分两个事务来操作该张表:
事务1:更新MANUAL_FREE2表的部分数据信息,也先不提交:
begin
delete from T_MANUAL_FREE2 t
where t.id between 18 and 20 ;
end;
 
事务2:向T_MANUAL_FREE2表中插入数据,也先不提交事务,如下:
  declare
   a char(1000);
   begin
   a:='ddd';
   for i in 1..2 loop
   insert into T_MANUAL_FREE2 values(i,a); 
   end loop;
   end;
则查看segment header的信息为:
*** 2008-03-29 20:46:37.187
Start dump data blocks tsn: 13 file#: 11 minblk 17 maxblk 21
buffer tsn: 13 rdba: 0x02c00011 (11/17)
scn: 0x0000.00181f15 seq: 0x01 flg: 0x00 tail: 0x1f151001
frmt: 0x02 chkval: 0x0000 type: 0x10=DATA SEGMENT HEADER - UNLIMITED
 Extent Control Header
 -----------------------------------------------------------------
 Extent Header:: spare1: 0       spare2: 0      #extents: 1      #blocks: 7    
                  last map 0x00000000 #maps: 0      offset: 4128 
      Highwater:: 0x02c00015 ext#: 0      blk#: 3      ext size: 7    
 #blocks in seg. hdr's freelists: 2    
 #blocks below: 3     
 mapblk 0x00000000 offset: 0     
                   Unlocked
     Map Header:: next 0x00000000 #extents: 1    obj#: 32112 flag: 0x40000000
 Extent Map
 -----------------------------------------------------------------
   0x02c00012 length: 7    
 
 nfl = 2, nfb = 1 typ = 1 nxf = 1 ccnt = 2
  SEG LST:: flg: USED   lhd: 0x02c00014 ltl: 0x02c00014
 SEG LST:: flg: UNUSED lhd: 0x00000000 ltl: 0x00000000
 SEG LST:: flg: USED   lhd: 0x02c00012 ltl: 0x02c00012
 XCT LST:: flg: UNUSED lhd: 0x00000000 ltl: 0x00000000 xid: 0x0000.000.00000000 
buffer tsn: 13 rdba: 0x02c00012 (11/18)
scn: 0x0000.00181f1c seq: 0x02 flg: 0x00 tail: 0x1f1c0602
frmt: 0x02 chkval: 0x0000 type: 0x06=trans data
Block header dump: 0x02c00012
 Object id on Block? Y
 seg/obj: 0x7d70 csc: 0x00.181ec4 itc: 2 flg: O typ: 1 - DATA
     fsl: 0 fnx: 0x0 ver: 0x01
 
 Itl            Xid                  Uba         Flag Lck        Scn/Fsc
0x01    0x0009.009.00000484 0x00800a00.00ae.03 ----    2 fsc 0x0000.00000000
0x02    0x0007.006.000004a5 0x00800aee.0056.03 C---    0 scn 0x0000.00181dd8
 
提交事务之后的segment header 的信息如下:
Start dump data blocks tsn: 13 file#: 11 minblk 17 maxblk 21
buffer tsn: 13 rdba: 0x02c00011 (11/17)
scn: 0x0000.00181f15 seq: 0x01 flg: 0x00 tail: 0x1f151001
frmt: 0x02 chkval: 0x0000 type: 0x10=DATA SEGMENT HEADER - UNLIMITED
 Extent Control Header
 -----------------------------------------------------------------
 Extent Header:: spare1: 0       spare2: 0      #extents: 1      #blocks: 7    
                  last map 0x00000000 #maps: 0      offset: 4128 
      Highwater:: 0x02c00015 ext#: 0      blk#: 3      ext size: 7    
   #blocks in seg. hdr's freelists: 2    
 #blocks below: 3     
 mapblk 0x00000000 offset: 0     
                   Unlocked
     Map Header:: next 0x00000000 #extents: 1    obj#: 32112 flag: 0x40000000
 Extent Map
 -----------------------------------------------------------------
   0x02c00012 length: 7     
 nfl = 2, nfb = 1 typ = 1 nxf = 1 ccnt = 2
 SEG LST:: flg: USED    lhd: 0x02c00014 ltl: 0x02c00014 对应数据块 20
 SEG LST:: flg: UNUSED lhd: 0x00000000 ltl: 0x00000000
 SEG LST:: flg: USED    lhd: 0x02c00012 ltl: 0x02c00012 对应数据块 18
 XCT LST:: flg: UNUSED lhd: 0x00000000 ltl: 0x00000000 xid: 0x0000.000.00000000
buffer tsn: 13 rdba: 0x02c00012 (11/18)
scn: 0x0000.00181fd9 seq: 0x01 flg: 0x02 tail: 0x1fd90601
frmt: 0x02 chkval: 0x0000 type: 0x06=trans data
Block header dump: 0x02c00012
 Object id on Block? Y
 seg/obj: 0x7d70 csc: 0x00.181ec4 itc: 2 flg: O typ: 1 - DATA
     fsl: 0 fnx: 0x0 ver: 0x01
 
 Itl            Xid                  Uba         Flag Lck        Scn/Fsc
0x01    0x0009.009.00000484 0x00800a00.00ae.03 --U-    2 fsc 0x0000.00181fd9
0x02    0x0007.006.000004a5 0x00800aee.0056.03 C---    0 scn 0x0000.00181dd8
分析:比较提交前后,发现红色标识的部分没有发生变化;
      说明两个进程同时进行时,各自在自己的PFL中的数据块都能够满足要求,一个删除数据,并没有使得对应的数据块所用空间低于PCTUSED所定义的限制,所以该PFL中的链表中的空闲数据块的个数并没有增多;同时,插入事务也没有因为PFL中的可用空间放不下而进行行链接也并没有新增数据块提高HWM,所以segment header中的信息和原来的一样。
此时查看
SQL> select t.id,dbms_rowid.rowid_object(rowid) data_object_id#,
 2          dbms_rowid.rowid_relative_fno(rowid) rfile#,
 3          dbms_rowid.rowid_block_number(rowid) block#,
 4          dbms_rowid.rowid_row_number(rowid) row#
 5     from T_MANUAL_FREE2 t;
 
        ID DATA_OBJECT_ID#     RFILE#     BLOCK#       ROW#
---------- --------------- ---------- ---------- ----------
         1           32112         11         18          0
         1           32112         11         18          1— 新插入的数据是插入到数据块 18 中的
         2           32112         11         18          2
         7           32112         11         18          6
         8           32112         11         19          0
         9           32112         11         19          1
        10           32112         11         19          2
        11           32112         11         19          3
        12           32112         11         19          4
        13           32112         11         19          5
        14           32112         11         19          6
        15           32112         11         20          0
        16           32112         11         20          1
        17           32112         11         20          2 数据块 20 中的 ID 18 20 的记录被删除
14 rows selected
分析:可以看出2个事务分别在2个PFL中并发进行各自做各自的操作;为什么说并发操作是因为由于在未提交事务时,一个删除操作的进程占用了一个PFL中的一个可用数据块20,则另一个进程则不允许再对数据块20再继续操作,所以需要另一个PFL链表中的另一个可用数据块18来进行插入操作,所以说2个进程是并发进行的;如果插入的数据所占的空间比较大以至数据块18不能插入,则提升HWM标志,进行行链接,新增一个数据块,向新的数据块中继续插入;如果所在的segment 的HWM上的空闲数据块为0,没有可用空间了,则需要分配新的extent,新分配的extent在只有一个MFL的时候其数据快转移到MFL,为PFL提供可用空间;
 
测试4: 下面证明 MFL PFL 可用空间是可以从 TFL 中获取数据块的
drop table T_MANUAL_FREE2

 create table T_MANUAL_free2
(
 ID    NUMBER,
 NAME VARCHAR2(1000)
)
tablespace TS_MAMUAL
 pctfree 10
 pctused 40
 initrans 1
 maxtrans 255
 storage
 (
    initial 64K   
    minextents 1
    freelists 2
    freelist groups 1
    maxextents unlimited
 );
 
重新插入数据,如下:
   declare
   a char(1000);
   begin
   a:='aaaa';
   for i in 1..38   loop
   insert into T_MANUAL_FREE2 values(i,a);
   commit;
   end loop;
   end;
  
begin
show_space('T_MANUAL_FREE2');
end;
 
Free Blocks.............................2
l_free_blks2
Total Blocks............................8
Total Bytes.............................65536
Unused Blocks...........................0
Unused Bytes............................0
Last Used Ext FileId....................11
Last Used Ext BlockId...................17
Last Used Block.........................8
2on FREELIST,7used by table

alter system dump datafile 11 block min 17 block max 23;
查看segment header的信息:
*** 2008-03-30 09:24:16.808
Start dump data blocks tsn: 13 file#: 11 minblk 17 maxblk 23
buffer tsn: 13 rdba: 0x02c00011 (11/17)
scn: 0x0000.00187b81 seq: 0x02 flg: 0x00 tail: 0x7b811002
frmt: 0x02 chkval: 0x0000 type: 0x10=DATA SEGMENT HEADER - UNLIMITED
 Extent Control Header
 -----------------------------------------------------------------
 Extent Header:: spare1: 0       spare2: 0      #extents: 1      #blocks: 7    
                  last map 0x00000000 #maps: 0      offset: 4128 
      Highwater:: 0x02c00019 ext#: 0      blk#: 7      ext size: 7  -- 表示 HWM 已经到数据块 25  
  #blocks in seg. hdr's freelists: 2     -- 2 个空闲数据块
 #blocks below: 7                  -- HWM 标志下有 7 个数据块
 mapblk 0x00000000 offset: 0     
                   Unlocked
     Map Header:: next 0x00000000 #extents: 1    obj#: 32122 flag: 0x40000000
 Extent Map
 -----------------------------------------------------------------
   0x02c00012 length: 7     
 nfl = 2, nfb = 1 typ = 1 nxf = 0 ccnt = 0
 SEG LST:: flg: UNUSED lhd: 0x00000000 ltl: 0x00000000
 SEG LST:: flg: UNUSED lhd: 0x00000000 ltl: 0x00000000
   SEG LST:: flg: USED   lhd: 0x02c00017 ltl: 0x02c00018 freelists 链表中有空闲数据块 23 24 ,已数据块 23 在链头,数据块 24 在链尾
buffer tsn: 13 rdba: 0x02c00012 (11/18)
scn: 0x0000.00187b65 seq: 0x03 flg: 0x00 tail: 0x7b650603
frmt: 0x02 chkval: 0x0000 type: 0x06=trans data
Block header dump: 0x02c00012
 Object id on Block? Y
 seg/obj: 0x7d7a csc: 0x00.187b65 itc: 2 flg: - typ: 1 - DATA
     fsl: 0 fnx: 0x0 ver: 0x01
 
 Itl            Xid                  Uba         Flag Lck        Scn/Fsc
0x01    0x0008.013.00000560 0x0080066a.005b.31 C---    0 scn 0x0000.00187b65
0x02    0x0009.002.00000485 0x0080008d.00af.03 C---    0 scn 0x0000.00187b64
分析:此时MFL并没有投入使用,其MFL链表上的起始地址和结束地址都为0;
 
继续在上面的基础上删除一部分数据,希望看到FML上有空闲数据块,猜测TFL释放出来的数据块一般先分配给PFL,当所有的PFL都存在空闲数据块时,并且所有的PFL都在被使用中,并且所有的PFL中的的空闲数据块不够使用时;
1)如果此时还有TFL存在,则FML等待TFL释放空闲数据块,这些被释放的数据块被LINK到MFL中,然后MFL移动空闲数据块到PFL,供PFL使用;
2)如果此时没有TFL存在,则需要尝试提升HWM;
3)如果提升失败,即HWM标志之上没有空闲数据块存在,则需要分配新的extent,分配新的extent的数据块将link到MFL或者PFL中
下面开始测试上面的猜想:
先删除一个数据块上的数据使它link到freelist链表上,然后再做插入操作使得这个可用数据块上的空间不是太大;为了防止在做插入操作时,新插入的数据向另一个链表中插入数据,则需要将链表处于一个事务中;
事务1:
 
 declare
   a char(1000);
   begin
   a:='ddd';
   for i in 2..6   loop
   insert into T_MANUAL_FREE2 values(i,a); 
   end loop;
   end;
事务2:
delete from T_MANUAL_FREE2 t
where t.id between 1 and 6
 
再开始分两个事务来操作该张表:
事务1:更新MANUAL_FREE2表的部分数据信息,也先不提交:
begin
delete from T_MANUAL_FREE2 t
where t.id=17 ;
end;
提交事务之后的segment header的信息:
Start dump data blocks tsn: 13 file#: 11 minblk 17 maxblk 23
buffer tsn: 13 rdba: 0x02c00011 (11/17)
scn: 0x0000.00187eef seq: 0x01 flg: 0x04 tail: 0x7eef1001
frmt: 0x02 chkval: 0x3981 type: 0x10=DATA SEGMENT HEADER - UNLIMITED
 Extent Control Header
 -----------------------------------------------------------------
 Extent Header:: spare1: 0       spare2: 0      #extents: 1      #blocks: 7    
                  last map 0x00000000 #maps: 0      offset: 4128 
      Highwater::  0x02c00019 ext#: 0      blk#: 7      ext size: 7    
  #blocks in seg. hdr's freelists: 3    
 #blocks below: 7     
 mapblk 0x00000000 offset: 0     
                   Unlocked
     Map Header:: next 0x00000000 #extents: 1    obj#: 32122 flag: 0x40000000
 Extent Map
 -----------------------------------------------------------------
   0x02c00012 length: 7    
 
 nfl = 2, nfb = 1 typ = 1 nxf = 1 ccnt = 1 – 这个也发生了变化,但是不知道什么含义?
  SEG LST:: flg: USED   lhd: 0x02c00012 ltl: 0x02c00012
 SEG LST:: flg: UNUSED lhd: 0x00000000 ltl: 0x00000000
 SEG LST:: flg: USED    lhd: 0x02c00017 ltl: 0x02c00018
  XCT LST:: flg: UNUSED lhd: 0x00000000 ltl: 0x00000000 xid: 0x0000.000.00000000
buffer tsn: 13 rdba: 0x02c00012 (11/18)
scn: 0x0000.00187eef seq: 0x01 flg: 0x04 tail: 0x7eef0601
frmt: 0x02 chkval: 0x74b1 type: 0x06=trans data
Block header dump: 0x02c00012
 Object id on Block? Y
 seg/obj: 0x7d7a csc: 0x00.187b65 itc: 2 flg: O typ: 1 - DATA
     fsl: 2 fnx: 0x0 ver: 0x01
 
 Itl            Xid                  Uba         Flag Lck        Scn/Fsc
0x01    0x0008.013.00000560 0x0080066a.005b.31 C---    0 scn 0x0000.00187b65
0x02    0x0006.018.000004fb 0x0080005d.005b.04 ----    7 fsc 0x179a.00000000
分析:在做提交事务之后,发现TFL中的事务并没有立即提交,出现下面的情况:
 Extent Control Header
 -----------------------------------------------------------------
 Extent Header:: spare1: 0       spare2: 0      #extents: 1      #blocks: 7
                  last map 0x00000000 #maps: 0      offset: 4128
      Highwater:: 0x02c00019 ext#: 0      blk#: 7      ext size: 7
  #blocks in seg. hdr's freelists: 3  -- 发现空闲数据块已经比事务发生之前多了一个数据块
 #blocks below: 7
 mapblk 0x00000000 offset: 0
                   Unlocked
     Map Header:: next 0x00000000 #extents: 1   obj#: 32122 flag: 0x40000000
 Extent Map
 -----------------------------------------------------------------
   0x02c00012 length: 7
 nfl = 2, nfb = 1 typ = 1 nxf = 1 ccnt = 0
 SEG LST:: flg: UNUSED lhd: 0x00000000 ltl: 0x00000000
 SEG LST:: flg: UNUSED lhd: 0x00000000 ltl: 0x00000000
 SEG LST:: flg: USED    lhd: 0x02c00017 ltl: 0x02c00018
  XCT LST:: flg: USED   lhd: 0x02c00012 ltl: 0x02c00012 xid: 0x0006.018.000004fb –但是 TFL 的信息并没有立即作修改;这个在测试在过程中觉得很奇怪。但是重新启动之后才
发现如下:
SEG LST:: flg: USED   lhd: 0x02c00012 ltl: 0x02c00012
 SEG LST:: flg: UNUSED lhd: 0x00000000 ltl: 0x00000000
 SEG LST:: flg: USED    lhd: 0x02c00017 ltl: 0x02c00018
  XCT LST:: flg: UNUSED lhd: 0x00000000 ltl: 0x00000000 xid: 0x0000.000.00000000 –TFL 0 了,并且数据块 18link MFL 或者 PFL 中去
 
继续删除一个数据块上的数据使它link到freelist链表上,然后再做插入操作使得这个可用数据块上的空间不是太大;为了防止在做插入操作时,新插入的数据向另一个链表中插入数据,则需要将链表处于一个事务中;
事务1:
 
delete from T_MANUAL_FREE2 t
where t.id between 5 and 6
事务2:
delete from T_MANUAL_FREE2 t
where t.id between 1 and 6
 
事务2:向T_MANUAL_FREE2表中插入数据,也先不提交事务,如下:
   declare
   a char(1000);
   begin
   a:='ddd';
   for i in 2..6   loop
   insert into T_MANUAL_FREE2 values(i,a); 
   end loop;
   end;
declare
   a char(1000);
   begin
   a:='ddd';
   for i in 2..6   loop
   insert into T_MANUAL_FREE2 values(i,a); 
   end loop;
   end;
提交之后的信息的如下:
 Extent Control Header
 -----------------------------------------------------------------
 Extent Header:: spare1: 0       spare2: 0      #extents: 2      #blocks: 15   
                  last map 0x00000000 #maps: 0      offset: 4128 
      Highwater:: 0x02c0002e ext#: 1      blk#: 5      ext size: 8    
   #blocks in seg. hdr's freelists: 7 --freelists 链表下有 7 个空闲数据块,由原来的 3 个变为 7 个,多出 4 个是由 extent 的增多而多出来的。  
 #blocks below: 12             --HWM 标志下有 12 个数据块 , 因为 extent 中的数据块书分配给了 freelist 中了,又由于 freelists 是主要管理 HWM 以下的空闲数据块,这样分析出来自然 HWM 要提升出来的数据块必定等于分配 extent 的数据块的个数,计算下: 12-7=4 HWM 比原来多 4 个数据块,正好等于 extents 的数据块,等于 freelists 链表中多出的数据块的个数。
 mapblk 0x00000000 offset: 1     
                   Unlocked
     Map Header:: next 0x00000000  #extents: 2    obj#: 32122 flag: 0x40000000
 Extent Map                      -- extents 变为 2 ,增加了一个 extents
 -----------------------------------------------------------------
   0x02c00012 length: 7    
   0x02c00029 length: 8     -- 猜测这个表示 extent 内的信息, 0x02c00029 表示这个 extent 的保存数据的起始地址,因为这个是随 extents 的个数变多增加出来的  
 nfl = 2, nfb = 1 typ = 1 nxf = 1 ccnt = 2
 SEG LST:: flg: UNUSED lhd: 0x00000000 ltl: 0x00000000
  SEG LST:: flg: USED   lhd: 0x02c00029 ltl: 0x02c0002d -- 链表 1 ,分配的 extent 空闲
数据块分配给了这个链表
  SEG LST:: flg: USED   lhd: 0x02c00017 ltl: 0x02c00018  -- 链表 2
 XCT LST:: flg: UNUSED lhd: 0x00000000 ltl: 0x00000000 xid: 0x0000.000.00000000
分析:由于插入操作我误操作了插入了2遍,又由于原来的链表1的不能容纳下这么多的插入数据,同时链表2也被事务1占用,所以没有其他的可用空间可用,此时一个segment空间也容纳不下新插入的数据,则这个时候oracle给这张表分配了一个extent,从上面的信息可以看出来,extents的个数由原来的1变为2;分配的extent数据块已经分配给PFL或者MFL链表中去了。这里我并没有发现MFL与PFL之间的调度数据块的关系;
 
以上主要测试了PFL,TFL以及HWM的变化情况,以及空闲数据块是如何分配的,感觉
设计的测试比较的简单,不过也学习了,大家看看还没有什么好的测试建议?对segment header上的参数我还是没有很清楚的理解,比如ccnt,xid的格式是表示什么意思?
 
简单总结下:
定义的freelists=2,freelistgroups=1的表,假设有2个事务,同时有2个feelists链表,则进程是按照下面的流程来申请空闲是数据块的。
1、freelists仅管理HWM之下的空闲数据块;
2、extents的分配的数据块是分配给PFL,MFL的链表中,即表示是这部分空闲数据块是属于freelists管理的,则表示这部分空闲块是在HWM标志之下的;
3、对于TFL,主要是分配给事务的,一个事务没有结束,是不会将空闲数据块释放的;但是一旦提交了事务,TFL中的数据块就会被链接到freelists链表中去,但是不会立即修改其TFL的使用使用情况,我在上面的例子看出的;
4、当多个事物同时进行时,空闲数据块的分配是按照下面的步骤分配的:
一个事务T1做插入操作,一个事务T2做删除操作;链表F1,F2
T2删除的数据正好是F2链表中的一个空闲数据块,则F2作为PFL供进程T2使用,此时还没有提交;
T1在T2做删除操作的同时进行插入操作,占用了F1链表:
1) 如果F1链表中的空闲数据块足够F1的数据的插入,则不会影响到HWM的提升的;
2) 如果F1链表中的空闲数据块不够F1的数据的插入,但是尽管F2链表中有空闲的数据块,但是F2链表已经被F2事务所占用,此时没有空闲的数据块可用,则需要进行行链接,需要新增新的数据块,如果HWM标志之上还有空闲数据块,则HWM可以提升成功;如果HWM提升失败,则转3)
3) 如果HWM提升失败,即HWM之上没有空闲数据块,则表示该segment已满,需要新增extent来满足空闲数据块的需求;
5、从上面测试可以看出,所有freelists信息都是存放在segment header之上的,这样当有多个进程同时需要修改各自的PFL链表的信息或者一PFL链表频繁需要更改时,再加上对freelists操作是将持有独占锁,这样会有对segment header block的争用;
6、不仅会有对segment header block的争用,当有多个进程都需要重新分配extent时,这样就都需要提升HWM,也会造成对HWM修改的争用;
 
问题:
1) 对于PFL以及MFL2种链表是如何相互移动空闲数据块的?我不知道怎么测试?大家有什么想法吗?
2) 对于MFL与freelistgroups之间是如何相互影响的?
 

你可能感兴趣的:(Oracle)