Oracle中ASSM模式下,向表中插入資料後被cache在記憶體的資料塊

PiscesCanon發表於2017-06-19
前言:
其實是一個小問題,不過就是要一點點的進歩,不用在乎進歩多少(給懶惰的自己一個安慰的理由= =)。
遇到問題就是要鍥而不捨的探究,也許結果並不怎麼重要,不過探究的過程有趣,卻又幫助自己瞭解oracle。
在學習ASSM遇到的小問題,本來想看看插入資料時候,被讀入buffer cache的資料塊是否如自己想的,結果有差別。
最後,問題的提出在比較後邊一點,因為要先構造環境,根據環境提出問題。

作業系統版本:
  1. [oracle@oracle trace]$ uname -a
  2. Linux oracle.example.com 2.6.32-431.el6.x86_64 #1 SMP Sun Nov 10 22:19:54 EST 2013 x86_64 x86_64 x86_64 GNU/Linux
  3. [oracle@oracle trace]$ lsb_release -a
  4. LSB Version:     :base-4.0-amd64:base-4.0-noarch:core-4.0-amd64:core-4.0-noarch:graphics-4.0-amd64:graphics-4.0-noarch:printing-4.0-amd64:printing-4.0-noarch
  5. Distributor ID:  RedHatEnterpriseServer
  6. Description:     Red Hat Enterprise Linux Server release 6.5 (Santiago)
  7. Release:         6.5
  8. Codename:        Santiago

資料庫版本:
  1. SYS@proc> select * from v$version where rownum=1;

  2. BANNER
  3. --------------------------------------------------------------------------------
  4. Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production

構造環境:
  1. SYS@proc> drop tablespace abc including contents;

  2. Tablespace dropped.

  3. SYS@proc> create tablespace abc datafile '/u01/app/oracle/oradata/proc/abc01.dbf' size 50m reuse uniform size 1m;

  4. Tablespace created.

  5. SYS@proc> create table aa(id int,name varchar(2)) tablespace abc;

  6. Table created.

  7. SYS@proc> select file#,DBABLK,state from x$bh where obj=(select data_object_id from dba_objects where owner='SYS' and object_name='AA') and state!=0 order by dbablk;

  8.      FILE#     DBABLK      STATE
  9. ---------- ---------- ----------
  10.          7        128          1
  11.          7        129          1
  12.          7        130          1
  13.          7        131          1

  14. SYS@proc> select extent_id,file_id,block_id,blocks from dba_extents where owner='SYS' and segment_name='AA';

  15.  EXTENT_ID    FILE_ID   BLOCK_ID     BLOCKS
  16. ---------- ---------- ---------- ----------
  17.          0          7        128        128

  18. SYS@proc> select HEADER_FILE,HEADER_BLOCK from dba_segments where owner='SYS' and segment_name='AA';

  19. HEADER_FILE HEADER_BLOCK
  20. ----------- ------------
  21.           7          131    --file7block131是L3塊

對L3塊做dump操作,以下是部分trace內容:
  1. Extent Control Header
  2.   -----------------------------------------------------------------
  3.   Extent Header:: spare1: 0 spare2: 0 #extents: 1 #blocks: 128
  4.                   last map 0x00000000 #maps: 0 offset: 2716
  5.       Highwater:: 0x01c00084 ext#: 0 blk#: 4 ext size: 128
  6.   #blocks in seg. hdr's freelists: 0
  7.   #blocks below: 0
  8.   mapblk 0x00000000 offset: 0
  9.                    Unlocked
  10.   --------------------------------------------------------
  11.   Low HighWater Mark :
  12.       Highwater:: 0x01c00084 ext#: 0 blk#: 4 ext size: 128
  13.   #blocks in seg. hdr's freelists: 0
  14.   #blocks below: 0
  15.   mapblk 0x00000000 offset: 0
  16.   Level 1 BMB for High HWM block: 0x01c00080
  17.   Level 1 BMB for Low HWM block: 0x01c00080
  18.   --------------------------------------------------------
  19.   Segment Type: 1 nl2: 1 blksz: 8192 fbsz: 0
  20.   L2 Array start offset: 0x00001434
  21.   First Level 3 BMB: 0x00000000
  22.   L2 Hint for inserts: 0x01c00082
  23.   Last Level 1 BMB: 0x01c00081
  24.   Last Level II BMB: 0x01c00082
  25.   Last Level III BMB: 0x00000000
  26.      Map Header:: next 0x00000000 #extents: 1 obj#: 89427 flag: 0x10000000
  27.   Inc # 0
  28.   Extent Map
  29.   -----------------------------------------------------------------
  30.    0x01c00080 length: 128

  31.   Auxillary Map
  32.   --------------------------------------------------------
  33.    Extent 0 : L1 dba: 0x01c00080 Data dba: 0x01c00084
  34.   --------------------------------------------------------

  35.    Second Level Bitmap block DBAs
  36.    --------------------------------------------------------
  37.    DBA 1: 0x01c00082

  38. End dump data blocks tsn: 23 file#: 7 minblk 131 maxblk 131
從L3的trace內容得到:
1.L2塊是0x01c00082,即7號檔案130號塊。
2.L1塊是0x01c00080,即7號檔案128號塊(不是準確的)。

可以dumpL2塊獲得所有的L1塊:
  1. Dump of Second Level Bitmap Block
  2.    number: 2 nfree: 2 ffree: 0 pdba: 0x01c00083
  3.    Inc #: 0 Objd: 89427
  4.   opcode:0
  5.  xid:
  6.   L1 Ranges :
  7.   --------------------------------------------------------
  8.    0x01c00080 Free: 5 Inst: 1
  9.    0x01c00081 Free: 5 Inst: 1

  10.   --------------------------------------------------------
  11. End dump data blocks tsn: 23 file#: 7 minblk 130 maxblk 130
從L2的trace內容得到:L1塊有7號檔案的128和129兩個塊。

分別dump128和129得到:
1.128中的資料塊範圍是:長度64,128-191
2.129中的資料塊範圍是:長度64,192-255
dump過程省略。

環境構造完成,並附上基本說明。
提出問題
按照ASSM下插入資料尋找塊的過程(受到高水位線影響),Oracle首先尋找L3號塊,根據L3中L2 Hint for inserts(本例為L2 Hint for inserts: 0x01c00082)確定L2號塊。然後確定L1號塊卻是根據PID做HASH隨機得到一個N值,在L2中確定了第N號的L1之後,根據PID做HASH再次得到一個隨機數M,並將資料插入L1中M號資料塊。
根據這個過程,那麼如果我向本例的AA表插入一行資料,被讀進buffer cache的塊就應該是L3(131號),L2(130號),L1(128號,因為高水位線是132號塊),和資料塊(132號)。

實驗過程:
  1. SYS@proc> select file#,DBABLK,state from x$bh where obj=(select data_object_id from dba_objects where owner='SYS' and object_name='AA') and state!=0 order by dbablk;

  2. no rows selected

  3. SYS@proc>
  4. SYS@proc> insert into aa values(1,'aa');

  5. 1 row created.

  6. SYS@proc> select file#,DBABLK,state from x$bh where obj=(select data_object_id from dba_objects where owner='SYS' and object_name='AA') and state!=0 order by dbablk;

  7.      FILE#     DBABLK      STATE
  8. ---------- ---------- ----------
  9.          7        128          1
  10.          7        129          1
  11.          7        130          1
  12.          7        131          3
  13.          7        131          1
  14.          7        144          1
  15.          7        145          1
  16.          7        146          1
  17.          7        147          1
  18.          7        148          1
  19.          7        149          1

  20.      FILE#     DBABLK      STATE
  21. ---------- ---------- ----------
  22.          7        150          1
  23.          7        151          1
  24.          7        152          1
  25.          7        153          1
  26.          7        154          1
  27.          7        155          1
  28.          7        156          1
  29.          7        157          1
  30.          7        158          1
  31.          7        159          1

  32. 21 rows selected.
看到這個結果很是不解,按照猜想,不應該讀入這麼多個塊。
於是嘗試rollback,並清空buffer cache,再次插入是什麼情況。
  1. SYS@proc> rollback;

  2. Rollback complete.

  3. SYS@proc> alter system flush buffer_cache;

  4. System altered.

  5. SYS@proc> select file#,DBABLK,state from x$bh where obj=(select data_object_id from dba_objects where owner='SYS' and object_name='AA') and state!=0 order by dbablk;

  6. no rows selected

  7. SYS@proc> insert into aa values(1,'aa');

  8. 1 row created.

  9. SYS@proc> select file#,DBABLK,state from x$bh where obj=(select data_object_id from dba_objects where owner='SYS' and object_name='AA') and state!=0 order by dbablk;

  10.      FILE#     DBABLK      STATE
  11. ---------- ---------- ----------
  12.          7        128          1
  13.          7        130          1
  14.          7        131          1
  15.          7        149          1
得到這個結果我之後,嘗試再次dump128號塊,得到以下結果(dump之前先flush buffer cache):
  1. --------------------------------------------------------
  2.   DBA Ranges :
  3.   --------------------------------------------------------
  4.    0x01c00080 Length: 64 Offset: 0

  5.    0:Metadata 1:Metadata 2:Metadata 3:Metadata
  6.    4:unformatted 5:unformatted 6:unformatted 7:unformatted
  7.    8:unformatted 9:unformatted 10:unformatted 11:unformatted
  8.    12:unformatted 13:unformatted 14:unformatted 15:unformatted
  9.    16:75-100% free 17:75-100% free 18:75-100% free 19:75-100% free
  10.    20:75-100% free 21:75-100% free 22:75-100% free 23:75-100% free
  11.    24:75-100% free 25:75-100% free 26:75-100% free 27:75-100% free
  12.    28:75-100% free 29:75-100% free 30:75-100% free 31:75-100% free
  13.    32:unformatted 33:unformatted 34:unformatted 35:unformatted
  14.    36:unformatted 37:unformatted 38:unformatted 39:unformatted
  15.    40:unformatted 41:unformatted 42:unformatted 43:unformatted
  16.    44:unformatted 45:unformatted 46:unformatted 47:unformatted
  17.    48:unformatted 49:unformatted 50:unformatted 51:unformatted
  18.    52:unformatted 53:unformatted 54:unformatted 55:unformatted
  19.    56:unformatted 57:unformatted 58:unformatted 59:unformatted
  20.    60:unformatted 61:unformatted 62:unformatted 63:unformatted
  21.   --------------------------------------------------------
  22. End dump data blocks tsn: 23 file#: 7 minblk 128 maxblk 128
可以看到塊中第16-31狀態變成“75-700% free”,那麼一開始插入那麼多塊被讀入buffer cache的原因就很清楚了,第16-31剛好對應144-159,而rollback之後重新插入卻只有四個塊,是因為已經格式化過資料塊了。

但是這裡卻有了另外一個問題,根據原先的提出“如果我向本例的AA表插入一行資料,被讀進buffer cache的塊就應該是L3(131號),L2(130號),L1(128號,因為高水位線是132號塊),和資料塊(132號)。”,是的,第二次的4個塊是128,130,131和149,而我們猜測的卻是128,130,131和132。
我們猜測132是因為插入資料時,高水位線是132號塊,但是這裡卻超過高水位線132去插入149,難道還有這種操作,我覺得Oracle顯然不會這樣,可能因為是格式化資料塊的時候,高水位線也變化了,根據變化規則,猜測高水位線應該變到了192號塊。
dump一下L3看看吧。
  1. Extent Control Header
  2.   -----------------------------------------------------------------
  3.   Extent Header:: spare1: 0 spare2: 0 #extents: 1 #blocks: 128
  4.                   last map 0x00000000 #maps: 0 offset: 2716
  5.       Highwater:: 0x01c000c0 ext#: 0 blk#: 64 ext size: 128
  6.   #blocks in seg. hdr's freelists: 0
  7.   #blocks below: 60
  8.   mapblk 0x00000000 offset: 0
  9.                    Unlocked
  10.   --------------------------------------------------------
  11.   Low HighWater Mark :
  12.       Highwater:: 0x01c00084 ext#: 0 blk#: 4 ext size: 128
  13.   #blocks in seg. hdr's freelists: 0
  14.   #blocks below: 0
  15.   mapblk 0x00000000 offset: 0
  16.   Level 1 BMB for High HWM block: 0x01c00080
  17.   Level 1 BMB for Low HWM block: 0x01c00080
  18.   --------------------------------------------------------
  19.   Segment Type: 1 nl2: 1 blksz: 8192 fbsz: 0
  20.   L2 Array start offset: 0x00001434
  21.   First Level 3 BMB: 0x00000000
  22.   L2 Hint for inserts: 0x01c00082
  23.   Last Level 1 BMB: 0x01c00081
  24.   Last Level II BMB: 0x01c00082
  25.   Last Level III BMB: 0x00000000
  26.      Map Header:: next 0x00000000 #extents: 1 obj#: 89427 flag: 0x10000000
  27.   Inc # 0
  28.   Extent Map
  29.   -----------------------------------------------------------------
  30.    0x01c00080 length: 128

  31.   Auxillary Map
  32.   --------------------------------------------------------
  33.    Extent 0 : L1 dba: 0x01c00080 Data dba: 0x01c00084
  34.   --------------------------------------------------------

  35.    Second Level Bitmap block DBAs
  36.    --------------------------------------------------------
  37.    DBA 1: 0x01c00082

  38. End dump data blocks tsn: 23 file#: 7 minblk 131 maxblk 131
可以看到Highwater:: 0x01c000c0剛好就是7號檔案192號塊,確實就符合了,插入時此處固定會讀取128,130,131,然後隨機選擇132-191的資料庫插入資料(當然不包括高水位線192塊了)。


其他資料:

插入一行資料格式的資料塊個數是不固定的,有過5個,16個,32個,64個等。

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

在L1塊中關於資料塊的狀態有7種格式:Unformat       75-100%       50-75%       25-50%      0-25%   FULL    Metadata

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/30174570/viewspace-2140927/,如需轉載,請註明出處,否則將追究法律責任。

相關文章