ASSM数据并发插入测试

Oracle内核技术揭密_吕海波  学习笔记

创建一个区大小为1M的表空间TEM_TBS1,在它里面建表ma.t64,插入一笔资料后可以看到为此表分配的第一个区的区间是从第128号块开始的共128个数据块,段头(L3块)为131号块。通过dump数据块的信息可以知道131号块为L3块,130号块为L2块,128、129号块为L1块(dump步骤查看通过dump数据块信息,追溯三层结构位图信息),每个L1块记录64个数据块信息。测试插入的第一笔数据放在190号数据块,并且是块中的第一行数据(row_id为0)。换一个会话进程,插入第二笔数据,oracle会根据PID计算出一个新的HASH值来确定存放该数据的块号,通过代码可以看到第二笔数据放在251号块中。再在第一个会话进程中插入第三笔数据,由于PID没变,所以第三笔数据仍然放在了190号数据块中,并且是第二行(row_id为1)。后面共连接插入10笔数据后,发现数据基本是均匀分布在128-255这128个块中(当然可以先去掉128-131这4个L块,它们不存放插入的数据行)。

SQL> CREATE TABLESPACE TEM_TBS1 DATAFILE '/data1/oradata/ora1/tem_tps101.dbf' SIZE 100M uniform size 1M;
SQL> create table ma.t64(id number(5),name varchar2(10)) tablespace TEM_TBS1;
SQL> insert into ma.t64 values(1,'a1');
SQL> commit;
SQL> select extent_id,file_id,block_id,blocks from dba_extents where owner='MA' and segment_name='T64' order by extent_id;

 EXTENT_ID    FILE_ID   BLOCK_ID     BLOCKS
---------- ---------- ---------- ----------
         0          7        128        128

SQL> select owner,segment_name,header_file,header_block from dba_segments where owner='MA' and segment_name='T64';

OWNER        SEGMENT_NAME    HEADER_FILE     HEADER_BLOCK
------       ------------    -----------     ------------
MA           T64             7               131

SQL> select DBMS_ROWID.ROWID_RELATIVE_FNO(rowid) file_id,DBMS_ROWID.ROWID_BLOCK_NUMBER(rowid) block_id,DBMS_ROWID.ROWID_ROW_NUMBER(rowid) row_id,id,name from ma.t64;

   FILE_ID   BLOCK_ID     ROW_ID         ID NAME
---------- ---------- ---------- ---------- ----------
         7        190          0          1 a1

SQL> insert into ma.t64 values(2,'b2');
SQL> commit;
SQL> select DBMS_ROWID.ROWID_RELATIVE_FNO(rowid) file_id,DBMS_ROWID.ROWID_BLOCK_NUMBER(rowid) block_id,DBMS_ROWID.ROWID_ROW_NUMBER(rowid) row_id,id,name from ma.t64;

   FILE_ID   BLOCK_ID     ROW_ID         ID NAME
---------- ---------- ---------- ---------- ----------
         7        190          0          1 a1
         7        251          0          2 b2

SQL>  insert into ma.t64 values(3,'c3');
SQL> commit;
SQL> select DBMS_ROWID.ROWID_RELATIVE_FNO(rowid) file_id,DBMS_ROWID.ROWID_BLOCK_NUMBER(rowid) block_id,DBMS_ROWID.ROWID_ROW_NUMBER(rowid) row_id,id,name from ma.t64;

   FILE_ID   BLOCK_ID     ROW_ID         ID NAME
---------- ---------- ---------- ---------- ----------
         7        190          0          1 a1
         7        190          1          3 c3
         7        251          0          2 b2


SQL> select DBMS_ROWID.ROWID_RELATIVE_FNO(rowid) file_id,DBMS_ROWID.ROWID_BLOCK_NUMBER(rowid) block_id,DBMS_ROWID.ROWID_ROW_NUMBER(rowid) row_id,id,name from ma.t64;

   FILE_ID   BLOCK_ID     ROW_ID         ID NAME
---------- ---------- ---------- ---------- ----------
         7        132          0          4 d4
         7        134          0          8 h8
         7        136          0         10 j10
         7        184          0          5 e5
         7        190          0          1 a1
         7        190          1          3 c3
         7        249          0          6 f6
         7        251          0          2 b2
         7        253          0          7 g7
         7        255          0          9 i9

dump 131号块的信息,得到高水位线信息:

  Extent Control Header

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

  Extent Header:: spare1: 0      spare2: 0      #extents: 1      #blocks: 128

                  last map  0x00000000  #maps: 0      offset: 2716

      Highwater::  0x01c00100  ext#: 0      blk#: 128    ext size: 128

高水位线的数据块地址为0x01c00100,转化为二进制后,左边10位是文件号,右边22位是数据块号。

Highwater::  0x01c00100
二进制:0000 0001 1100 0000 0000 0001 0000 0000
前10位:(文件号) 0000 0001 11  = 7
后22位: (高水位线块号) 00 0000 0000 0001 0000 0000  = 256

因此高水位线为7号文件中的256号块,也呼应了之前在表ma.t64中插入的10条数据是在128-255号块中均匀分布的。两个L1块各记录64个数据块,刚好可以随机使用这128个数据块。但当如果高水位线停在192号块,这时相对路径插入只会使用前64个数据块,也就是只会使用128号这个L1块中记录的数据块,而不会使用129号这个L1块,这种情况与ASSM的随机分配数据块相冲突,在L2中找L1时不能做到完全随机。理论上此时的并发插入性能减半。之所以高水位线会停在192块,是有资料介绍:

“在区中插入第一行数据时,高水位线移到区的第一个L1块中最大的数据块后,L1记录的是128-191号块,此时的高水位线也就是在192号块;当块大小为8K,区大小为1M,这时L1中有64个数据块,高水位线就会以64个块为单位依次往后移动。刚开始ASSM的并发受高水位线的限制,当有100个进程插入资料,此时最多只能处理64个进程,这就会导致buffer busy waits。”

但个人在12C版本下测试的结果有所不同,块大小为8K,区大小为1M,高水位线刚开始就在256号块处,随着数据的增加,下一次发现高水位线在384号块处,也就是往后移动了128个块,是一个区的大小,也是2个L1块的大小。

随着空间使用的增多,L1的中记录的数据块也会增加。如下代码测试手动分配90M空间,有91个分区,然后dump出8号文件的11520号块(L1块)的信息,可以看到这个L1块中记录了256个数据块信息。

SQL> drop tablespace tbs2 including contents;
SQL> CREATE TABLESPACE TBS2 DATAFILE '/data1/oradata/ora1/tps201.dbf' SIZE 500M uniform size 1M;
SQL> create table ma.t65(id number(5),name varchar2(10)) tablespace tbs2;
SQL> alter table ma.t65 allocate extent (size 90m);
SQL> set pagesize 1000
SQL> alter session set "_sga_clear_dump"=true;
SQL> alter system dump datafile 8 block 11520;
$ cd $ORACLE_BASE/diag/rdbms/$ORACLE_SID/$ORACLE_SID/trace


*** 2019-04-17 08:52:46.743
 04/17/2019 08:52:29 04/17/2019 08:52:29
Start dump data blocks tsn: 9 file#:8 minblk 11520 maxblk 11520
Block dump from cache:
Dump of buffer cache at level 4 for pdb=0 tsn=9 rdba=33565952
Block dump from disk:
Decrypting encrypted buffer before dump.
buffer tsn: 9 rdba: 0x02002d00 (8/11520)
scn: 0x0.44fdb5 seq: 0x04 flg: 0x04 tail: 0xfdb52004
frmt: 0x02 chkval: 0xc1b3 type: 0x20=FIRST LEVEL BITMAP BLOCK
Hex dump of block: st=0, typ_found=1
Dump of memory from 0x00007F8C7D1A0E00 to 0x00007F8C7D1A2E00
7F8C7D1A0E00 0000A220 02002D00 0044FDB5 04040000  [ ....-....D.....]
          ......
7F8C7D1A2DF0 00000000 00000000 00000000 FDB52004  [............. ..]
Dump of First Level Bitmap Block
 --------------------------------
   nbits : 4 nranges: 2         parent dba:  0x02000082   poffset: 139
   unformatted: 255     total: 256       first useful block: 1
   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 : 1
   Bitmap block lock opcode 3
   Locker xid:     :  0x000a.01e.00000556
   Dealloc scn: 3.0
   Flag: 0x00000000 (-/-/-/-/-/-)
   Inc #: 0 Objd: 93813
  --------------------------------------------------------
  DBA Ranges :
  --------------------------------------------------------
   0x02002d00  Length: 128    Offset: 0
   0x02002d80  Length: 128    Offset: 128

   0:Metadata   1:unformatted   2:unformatted   3:unformatted
   4:unformatted   5:unformatted   6:unformatted   7:unformatted
                    ......
   248:unformatted   249:unformatted   250:unformatted   251:unformatted
   252:unformatted   253:unformatted   254:unformatted   255:unformatted

也就是说对于每天一个分区的表,一天开始时,它里面的L1是相对较小的,也就是支持的并发量受L1中记录数据块多少限制的,随着数据量增加,区的使用增多,L1中的数据块信息也会增加,并发量也会增加。如果每天某一个比较早的时间段出现buffer busy waits这种事件,随着数据量增加,这个等待事件没有了,可以考虑是前期L1中数据块信息较少,高水位线低,影响了并发量。可以通过中间表,采用直接路径方式向表中插入数据,这样消耗undo少,再delete,这样来提升高水位线,再分区交换到正式表,这样可以解决并发问题。

此时我们再导出8号文件131号块,也就是L3块的信息,来看看数据库进行全表扫描时,是利用了L3块中的哪些有效信息。

SQL>  alter system dump datafile 8 block 131;

*** 2019-04-17 09:23:02.771
Start dump data blocks tsn: 9 file#:8 minblk 131 maxblk 131
Block dump from cache:
Dump of buffer cache at level 4 for pdb=0 tsn=9 rdba=33554563
Block dump from disk:
Decrypting encrypted buffer before dump.
buffer tsn: 9 rdba: 0x02000083 (8/131)
scn: 0x0.44fdb9 seq: 0x01 flg: 0x04 tail: 0xfdb92301
frmt: 0x02 chkval: 0xc5be type: 0x23=PAGETABLE SEGMENT HEADER
Hex dump of block: st=0, typ_found=1
Dump of memory from 0x00007F8C7D1A0E00 to 0x00007F8C7D1A2E00
7F8C7D1A0E00 0000A223 02000083 0044FDB9 04010000  [#.........D.....]
        ......
7F8C7D1A2DF0 00000000 00000000 00000000 FDB92301  [.............#..]
  Extent Control Header
  -----------------------------------------------------------------
  Extent Header:: spare1: 0      spare2: 0      #extents: 91     #blocks: 11648
                  last map  0x00000000  #maps: 0      offset: 2716
      Highwater::  0x02000084  ext#: 0      blk#: 4      ext size: 128
  #blocks in seg. hdr's freelists: 0
  #blocks below: 0
  mapblk  0x00000000  offset: 0
                   Unlocked
  --------------------------------------------------------
  Low HighWater Mark :
      Highwater::  0x02000084  ext#: 0      blk#: 4      ext size: 128
  #blocks in seg. hdr's freelists: 0
  #blocks below: 0
  mapblk  0x00000000  offset: 0
  Level 1 BMB for High HWM block: 0x02000080
  Level 1 BMB for Low HWM block: 0x02000080
  --------------------------------------------------------
  Segment Type: 1 nl2: 1      blksz: 8192   fbsz: 0
  L2 Array start offset:  0x00001434
  First Level 3 BMB:  0x00000000
  L2 Hint for inserts:  0x02000082
  Last Level 1 BMB:  0x02002d00
  Last Level II BMB:  0x02000082
  Last Level III BMB:  0x00000000
     Map Header:: next  0x00000000  #extents: 91   obj#: 93813  flag: 0x10000000
  Inc # 0
  Extent Map
  -----------------------------------------------------------------
   0x02000080  length: 128
   0x02000100  length: 128
      ......
   0x02002d00  length: 128
   0x02002d80  length: 128

  Auxillary Map
  --------------------------------------------------------
   Extent 0     :  L1 dba:  0x02000080 Data dba:  0x02000084
   Extent 1     :  L1 dba:  0x02000100 Data dba:  0x02000102
   Extent 2     :  L1 dba:  0x02000180 Data dba:  0x02000182
   Extent 3     :  L1 dba:  0x02000200 Data dba:  0x02000202
              ......
   Extent 87    :  L1 dba:  0x02002c00 Data dba:  0x02002c01
   Extent 88    :  L1 dba:  0x02002c00 Data dba:  0x02002c80
   Extent 89    :  L1 dba:  0x02002d00 Data dba:  0x02002d01
   Extent 90    :  L1 dba:  0x02002d00 Data dba:  0x02002d80
  --------------------------------------------------------

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


Extent Map记录了每个区的起始块位置,以及区的长度。这样就可以找到每一个区,以及区里的每一个块。如0x02000080,把这个十六进制转化为2进制,前十位是文件号,后面的就是块号,0x02000080代表的就是8号文件的128号块,也就是这个区的第一个块,通常第一个块是L1块。但随着L1中记录的数据块信息增加,如前面说的记录了256个块,那么一个L1可以记录两个区的信息(一个区是128个块),可以从辅助地图Auxillary Map中信息看出,Extent 87和Extent 88号区的L1地址都是0x02002c00。

辅助地图Auxillary Map中的Extent 0     :  L1 dba:  0x02000080 Data dba:  0x02000084这一行信息,是说在0号区中第一个L1块地址是128号块,L1中的数据块起始位置为132号块。

全表扫描就是通过段头读取区地图信息,再通过区地图信息读取数据信息。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值