ORACLE空間管理實驗6:塊管理之ASSM下插入操作--高水位的影響及大併發插入的效能問題

還不算暈發表於2014-01-27

一、資料塊的插入時尋找可用塊的規則總結:

高水位與低高水位:低高水位與高水位之間存在的資料塊的狀態可能是未格式化或格式的。低高水位以下的是格式化了的,可以被使用。
1.首先,插入一條資料,只會使用高水位以下的資料塊
高水點的位置:L1塊所包含資料塊的邊界,要麼是區的邊界

2.第一次插入一行資料,格式化塊數?
並沒有一個一定的數值,從DUMP L1塊中看,有格式化5個,32個64個等。

3.插入一行資料,如何通過L3-->L2-->L1--資料塊,這個過程來確定插入哪個塊?
在ASSM表空間下:一個行在不同會話上是被隨機插入高水位以下的不同的塊。
具體說明如下:
L3選擇L2,不隨機,根據L2 Hint for inserts:  0x01c00081 這一行,確定要選擇的L2。
在L2中,根據PID進行HASH,得到一個隨機值,根據此值選擇L1.--但是這受高水位影響,如果高水位範圍內只有一個區,事實上將只選擇這一個區對應的L1。
在L1中,根據PID進行HASH,得到一個隨機值,根據此值選擇資料塊。
--實驗時要注意,在同一視窗下,sqlplus快速退出再登陸,使用的是同一SID,所以插入的行會在同一資料塊。

4.多個會話各自插入一行資料,插入順序?

假設每行插入的資料所需要空間都不超過一個資料塊:
同一會話向一張表中插入資料,是有序的,並且是插入同一個資料塊。
如果多個會話向一張表中插入資料,是無序的,並且每個會話插入的資料在不同的資料塊。

也就是:多個會話的插入是無序的,同一會話下插入有先後順序。讀取資料時,預設按ROWID,升序讀取。

構造此實驗的語句與結果:

create table t1 (id number,name varchar2(10));
session1--
insert into t1 values(1,'a');
insert into t1 values(2,'a');
commit;
session2--
insert into t1 values(3,'a');
insert into t1 values(4,'a');
commit;
session3--
insert into t1 values(5,'a');
insert into t1 values(6,'a');
commit;
session1不退出--
insert into t1 values(7,'a');
insert into t1 values(8,'a');
commit;

select id,name,rowid from t1;

select rowid,id,name,dbms_rowid.rowid_relative_fno(rowid) file_id,
dbms_rowid.rowid_block_number(rowid) block_id,
dbms_rowid.rowid_row_number(rowid) row_id from t1;
SQL> select id,name,rowid from t1;
        ID NAME       ROWID
---------- ---------- ------------------
         1 a          AAADfoAAFAAAACFAAA
         2 a          AAADfoAAFAAAACFAAB
         5 a          AAADfoAAFAAAACFAAC
         6 a          AAADfoAAFAAAACFAAD
         7 a          AAADfoAAFAAAACFAAE
         8 a          AAADfoAAFAAAACFAAF
         3 a          AAADfoAAFAAAACHAAA
         4 a          AAADfoAAFAAAACHAAB
8 rows selected.
SQL> select rowid,id,name,dbms_rowid.rowid_relative_fno(rowid) file_id,
  2  dbms_rowid.rowid_block_number(rowid) block_id,dbms_rowid.rowid_row_number(rowid) row_id from t1;
ROWID                      ID NAME          FILE_ID   BLOCK_ID     ROW_ID
------------------ ---------- ---------- ---------- ---------- ----------
AAADfoAAFAAAACFAAA          1 a                   5        133          0
AAADfoAAFAAAACFAAB          2 a                   5        133          1
AAADfoAAFAAAACFAAC          5 a                   5        133          2
AAADfoAAFAAAACFAAD          6 a                   5        133          3
AAADfoAAFAAAACFAAE          7 a                   5        133          4
AAADfoAAFAAAACFAAF          8 a                   5        133          5
AAADfoAAFAAAACHAAA          3 a                   5        135          0
AAADfoAAFAAAACHAAB          4 a                   5        135          1

8 rows selected.

實驗:同一會話插入兩條語句,再開一新會話插入一條,通過DBMS_ROWID檢視行所在的資料塊,會發現同一會話下插入同一塊,不同會話不插入同一塊。太簡單了,沒巾出來。


二、高水位及putfree值設定不當引起的效能問題--熱塊導致buffer busy waits等待事件

插入一條資料,只會使用高水位以下的資料塊會引起的buffer busy waits效能問題?

首先,高水點的位置:L1塊所包含資料塊的邊界,要麼是區的邊界。
而一個L1或者一個區所包含的資料塊的個數是有限的。比如8KB在BLOCK時,系統自動管理區大小時,前16個區只有8個資料塊,1-64 M時區大小為1M,128個塊。64M以後的區大小是8M,有1024個資料塊。
在8M的區時,有1024個塊可以用,去除儲存後設資料的庫,假如有1000個塊可用,此時就是能支援1000個併發插入操作,有更多併發操作的時候,就不可避免的要出現多個會話同時向同一個資料塊進行操作,此時就出現了熱塊--等待事件buffer busy waits。

1000個併發其實已經很大了,多用在日誌型應用中。

如果併發超過1000個,並且buffer busy waits出現很多,已經影響到系統效能,有一個不太完美的解決方法是:在業務高峰來臨前,在表中大量插入一批資料,推高高水位的位置;然後再刪除資料,此時高水位之前有更多的資料塊可供插入,就可以支援更高的併發了。


引起buffer busy waits等待事件,還有一種可能就是不合理的PCTFREE值。

因為在ASSM中,在L1中用五種狀態: 75-100%       50-75%       25-50%      0-25%   FULL來表示資料塊的空閒狀態,如果設定的值靠近這個監界值,比如PUTFREE是20%或24%,此時可能對資料塊中資料進行幾行的插入、更新 或刪除就會導致資料塊狀態的改變,而資料塊狀態的改變,L1塊中也要發生相應的改變來記錄資料塊的狀態。
因為一個L1塊管理多個資料塊(比如8M區8KB資料塊時一個L1管理1024個資料塊),如果一個L1管理的多個資料塊都要同時更新塊的空間狀態,也會引起L1塊的爭用--熱塊--等待事件buffer busy waits。
這個也能實驗,不過不太好實驗,要用一行資料比較長,配合PCTFREE的值,做到刪除一行和插入一行或幾行,塊狀態就發生變化,此時DUMP L1塊來驗證。

ASSM缺點:

ASSM下資料和索引的順序不一致,導致聚簇因子增大



三、實驗:驗證插入的行預設只能插入到高水位以下的資料塊

思路:先建表,手動給表分配多個區。使用多個會話,每個會話插入一行資料,順便驗證資料塊的插入順序
#############################33
BYS@ bys3>create table test11(aa int ,bb varchar2(10));
Table created.
BYS@ bys3>insert into test11 values(99,'first');
1 row created.
BYS@ bys3>commit;
Commit complete.
BYS@ bys3>alter table test11  allocate extent(size 1m);
Table altered.
BYS@ bys3>alter system checkpoint;
System altered.
BYS@ bys3>select header_file,header_block from dba_segments where segment_name='TEST11' and owner='BYS';
HEADER_FILE HEADER_BLOCK
----------- ------------
          4          170
#####################

DUMP段頭:

 Extent Control Header   --高水位Highwater::  0x010000b0,在176號塊。也就是第一個區的最後一個塊。
  -----------------------------------------------------------------
  Extent Header:: spare1: 0      spare2: 0      #extents: 17     #blocks: 256   
                  last map  0x00000000  #maps: 0      offset: 2716  
      Highwater::  0x010000b0  ext#: 0      blk#: 8      ext size: 8     
  #blocks in seg. hdr's freelists: 0     
  #blocks below: 5     
  mapblk  0x00000000  offset: 0     
                   Unlocked
  --------------------------------------------------------
  Low HighWater Mark :   --低高水位此時和高水位的DBA是一個塊。
      Highwater::  0x010000b0  ext#: 0      blk#: 8      ext size: 8     
  #blocks in seg. hdr's freelists: 0     
  #blocks below: 5     
  mapblk  0x00000000  offset: 0     
  Level 1 BMB for High HWM block: 0x010000a8
  Level 1 BMB for Low HWM block: 0x010000a8
  --------------------------------------------------------
  Segment Type: 1 nl2: 1      blksz: 8192   fbsz: 0      
  L2 Array start offset:  0x00001434
  First Level 3 BMB:  0x00000000
  L2 Hint for inserts:  0x010000a9   ---L2的塊是169號塊
  Last Level 1 BMB:  0x01000101
  Last Level II BMB:  0x010000a9
  Last Level III BMB:  0x00000000
     Map Header:: next  0x00000000  #extents: 17   obj#: 22989  flag: 0x10000000
  Inc # 0
  Extent Map
  -----------------------------------------------------------------
   0x010000a8  length: 8     --第一個區的起始地址是0x010000a8,四號檔案,168號塊。
   0x010000b0  length: 8     --第二個區的起始地址是0x010000b0,4號檔案176號塊,與高水位的對應
   0x010000b8  length: 8     
   0x010000c0  length: 8     
   0x010000c8  length: 8     
   0x010000d0  length: 8     
   0x010000d8  length: 8     
   0x010000e0  length: 8     
   0x010000e8  length: 8     
   0x010000f0  length: 8     
   0x010001a8  length: 8     
   0x010001b0  length: 8     
   0x010001b8  length: 8     
   0x010001c0  length: 8     
   0x010001c8  length: 8     
   0x010001d0  length: 8     
   0x01000100  length: 128   
 
  Auxillary Map
  --------------------------------------------------------
   Extent 0     :  L1 dba:  0x010000a8 Data dba:  0x010000ab     ---這裡從L1 DBA可以看到,這一個L1管理了0和1號區。
   Extent 1     :  L1 dba:  0x010000a8 Data dba:  0x010000b0

   Extent 2     :  L1 dba:  0x010000b8 Data dba:  0x010000b9
   Extent 3     :  L1 dba:  0x010000b8 Data dba:  0x010000c0
   Extent 4     :  L1 dba:  0x010000c8 Data dba:  0x010000c9
   Extent 5     :  L1 dba:  0x010000c8 Data dba:  0x010000d0
   Extent 6     :  L1 dba:  0x010000d8 Data dba:  0x010000d9
   Extent 7     :  L1 dba:  0x010000d8 Data dba:  0x010000e0
   Extent 8     :  L1 dba:  0x010000e8 Data dba:  0x010000e9
   Extent 9     :  L1 dba:  0x010000e8 Data dba:  0x010000f0
   Extent 10    :  L1 dba:  0x010001a8 Data dba:  0x010001a9
   Extent 11    :  L1 dba:  0x010001a8 Data dba:  0x010001b0
   Extent 12    :  L1 dba:  0x010001b8 Data dba:  0x010001b9
   Extent 13    :  L1 dba:  0x010001b8 Data dba:  0x010001c0
   Extent 14    :  L1 dba:  0x010001c8 Data dba:  0x010001c9
   Extent 15    :  L1 dba:  0x010001c8 Data dba:  0x010001d0
   Extent 16    :  L1 dba:  0x01000100 Data dba:  0x01000102
  --------------------------------------------------------
   Second Level Bitmap block DBAs
   --------------------------------------------------------
   DBA 1:   0x010000a9
  ##############################################

  DUMP 第一個L1--也是高水位內的惟一一個L1

BYS@ bys3>alter system dump datafile 4 block 168;
System altered.
BYS@ bys3>select value from v$diag_info where name like 'De%';
VALUE
----------------------------------------------------------------------------------------------------
/u01/diag/rdbms/bys3/bys3/trace/bys3_ora_27244.trc
###############DUMP資訊如下:
  Dump of First Level Bitmap Block
 --------------------------------
   nbits : 4 nranges: 2         parent dba:  0x010000a9   poffset: 0     
   unformatted: 8       total: 16        first useful block: 3      
   owning instance : 1
   instance ownership changed at 01/25/2014 22:21:43
   Last successful Search 01/25/2014 22:21:43
   Freeness Status:  nf1 0      nf2 0      nf3 0      nf4 5      
 
   Extent Map Block Offset: 4294967295
   First free datablock : 3      
   Bitmap block lock opcode 3
   Locker xid:     :  0x0003.006.00001365
   Dealloc scn: 8820451.0
   Flag: 0x00000001 (-/-/-/-/-/HWM)
   Inc #: 0 Objd: 22989
  HWM Flag: HWM Set
      Highwater::  0x010000b0 
ext#: 0      blk#: 8      ext size: 8     
  #blocks in seg. hdr's freelists: 0     
  #blocks below: 5     
  mapblk  0x00000000  offset: 0     
  --------------------------------------------------------
  DBA Ranges :   ---從這裡也能驗證這個L1管理了兩個區,與段頭的  Auxillary Map可以對應。
  --------------------------------------------------------
   0x010000a8  Length: 8      Offset: 0      
   0x010000b0  Length: 8      Offset: 8      
 
   0:Metadata   1:Metadata   2:Metadata   3:75-100% free
   4:75-100% free   5:75-100% free   6:75-100% free   7:75-100% free
   8:unformatted   9:unformatted   10:unformatted   11:unformatted
   12:unformatted   13:unformatted   14:unformatted   15:unformatted
從DUMP資訊中可以看到,第一個L1的第一個塊168號塊,也是這個段的第一個塊的地址。
0:Metadata   1:Metadata   2:Metadata這三個對應的是168號塊L1,169號塊L2,170號塊是段頭--第一個L3。
高水位是在176號塊,也就是第二個區的第一個塊,這裡因為一個區只有8個塊,一個L1管理了兩個區。
插入一行資料,從以上DUMP資訊中可以看到,只格式化了高水位下的這個區。區中有三個是存放ASSM的管理資訊,所以事實上能用的塊是55個塊,也就是這次插入資料格式化了5個塊。。

注:在其它實驗中,插入一行資料格式的資料塊個數是不固定的,有過16個,32個,64個等。

插入一行資料格式化的資料塊數量應該是和區大小以及高水位位置有一定關係吧,總之格式化資料塊是按批進行的,具體一批是多少不清楚哈哈。

#######################3

現在使用下面指令碼同時啟動30個會話進行插入資料操作,然後檢視插入的ROWID資訊:

結果是;從查詢中可以看到,插入的資料塊都在高水位176這個資料塊之下,被隨機插入到了各個塊中。

[oracle@bys3 ~]$ cat insert.sql

sqlplus bys/bys <<EOF
insert into bys.test11 values($1,'hello');
commit;
exec dbms_lock.sleep(2000);
EOF

#######
./insert.sql 1 &
./insert.sql 2 &
./insert.sql 3 &
./insert.sql 4 &
./insert.sql 5 &
./insert.sql 6 &
./insert.sql 7 &
./insert.sql 8 &
./insert.sql 9 &
./insert.sql 10 &

./insert.sql 11 &
./insert.sql 12 &
./insert.sql 13 &
./insert.sql 14 &
./insert.sql 15 &
./insert.sql 16 &
./insert.sql 17 &
./insert.sql 18 &
./insert.sql 19 &
./insert.sql 20 &

./insert.sql 21 &
./insert.sql 22 &
./insert.sql 23 &
./insert.sql 24 &
./insert.sql 25 &
./insert.sql 26 &
./insert.sql 27 &
./insert.sql 28 &
./insert.sql 29 &
./insert.sql 30 &
####################插入完成後查詢:
BYS@ bys3>select dbms_rowid.ROWID_RELATIVE_FNO(rowid) fno,dbms_rowid.rowid_block_number(rowid) block#,aa,bb  from test11 order by  block#;
       FNO     BLOCK#         AA BB
---------- ---------- ---------- ----------
         4        171         99 first
         4        171          1 hello
         4        171          1 hello
         4        171          4 hello
         4        171         14 hello
         4        171         18 hello
         4        171         21 hello
         4        171         26 hello
         4        172          1 hello
         4        172         12 hello
         4        172         11 hello
         4        172         19 hello
         4        172         24 hello
         4        172         28 hello
         4        173          8 hello
         4        173         29 hello
         4        173         25 hello
         4        173         13 hello
         4        173         15 hello
         4        174         27 hello
         4        174         16 hello
         4        174          6 hello
         4        174          7 hello
         4        174          2 hello
         4        175          9 hello
         4        175          5 hello
         4        175         17 hello
         4        175         22 hello
         4        175         23 hello
         4        175          3 hello
從查詢中可以看到,插入的資料塊都在高水位176這個資料塊之下,被隨機插入到了各個塊中。

相關文章