其实是一个小问题,不过就是要一点点的进歩,不用在乎进歩多少(给懒惰的自己一个安慰的理由= =)。
遇到问题就是要锲而不舍的探究,也许结果并不怎么重要,不过探究的过程有趣,却又帮助自己了解oracle。
在学习ASSM遇到的小问题,本来想看看插入数据时候,被读入buffer cache的数据块是否如自己想的,结果有差别。
最后,问题的提出在比较后边一点,因为要先构造环境,根据环境提出问题。
操作系统版本:
-
[oracle@oracle trace]$ uname -a
-
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
-
[oracle@oracle trace]$ lsb_release -a
-
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
-
Distributor ID: RedHatEnterpriseServer
-
Description: Red Hat Enterprise Linux Server release 6.5 (Santiago)
-
Release: 6.5
- Codename: Santiago
数据库版本:
-
SYS@proc> select * from v$version where rownum=1;
-
-
BANNER
-
--------------------------------------------------------------------------------
- Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
构造环境:
-
SYS@proc> drop tablespace abc including contents;
-
-
Tablespace dropped.
-
-
SYS@proc> create tablespace abc datafile '/u01/app/oracle/oradata/proc/abc01.dbf' size 50m reuse uniform size 1m;
-
-
Tablespace created.
-
-
SYS@proc> create table aa(id int,name varchar(2)) tablespace abc;
-
-
Table created.
-
-
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;
-
-
FILE# DBABLK STATE
-
---------- ---------- ----------
-
7 128 1
-
7 129 1
-
7 130 1
-
7 131 1
-
-
SYS@proc> select extent_id,file_id,block_id,blocks from dba_extents where owner='SYS' and segment_name='AA';
-
-
EXTENT_ID FILE_ID BLOCK_ID BLOCKS
-
---------- ---------- ---------- ----------
-
0 7 128 128
-
-
SYS@proc> select HEADER_FILE,HEADER_BLOCK from dba_segments where owner='SYS' and segment_name='AA';
-
-
HEADER_FILE HEADER_BLOCK
-
----------- ------------
- 7 131 --file7block131是L3块
对L3块做dump操作,以下是部分trace内容:
-
Extent Control Header
-
-----------------------------------------------------------------
-
Extent Header:: spare1: 0 spare2: 0 #extents: 1 #blocks: 128
-
last map 0x00000000 #maps: 0 offset: 2716
-
Highwater:: 0x01c00084 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:: 0x01c00084 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: 0x01c00080
-
Level 1 BMB for Low HWM block: 0x01c00080
-
--------------------------------------------------------
-
Segment Type: 1 nl2: 1 blksz: 8192 fbsz: 0
-
L2 Array start offset: 0x00001434
-
First Level 3 BMB: 0x00000000
-
L2 Hint for inserts: 0x01c00082
-
Last Level 1 BMB: 0x01c00081
-
Last Level II BMB: 0x01c00082
-
Last Level III BMB: 0x00000000
-
Map Header:: next 0x00000000 #extents: 1 obj#: 89427 flag: 0x10000000
-
Inc # 0
-
Extent Map
-
-----------------------------------------------------------------
-
0x01c00080 length: 128
-
-
Auxillary Map
-
--------------------------------------------------------
-
Extent 0 : L1 dba: 0x01c00080 Data dba: 0x01c00084
-
--------------------------------------------------------
-
-
Second Level Bitmap block DBAs
-
--------------------------------------------------------
-
DBA 1: 0x01c00082
-
- End dump data blocks tsn: 23 file#: 7 minblk 131 maxblk 131
1.L2块是0x01c00082,即7号文件130号块。
2.L1块是0x01c00080,即7号文件128号块(不是准确的)。
可以dumpL2块获得所有的L1块:
-
Dump of Second Level Bitmap Block
-
number: 2 nfree: 2 ffree: 0 pdba: 0x01c00083
-
Inc #: 0 Objd: 89427
-
opcode:0
-
xid:
-
L1 Ranges :
-
--------------------------------------------------------
-
0x01c00080 Free: 5 Inst: 1
-
0x01c00081 Free: 5 Inst: 1
-
-
--------------------------------------------------------
- End dump data blocks tsn: 23 file#: 7 minblk 130 maxblk 130
分别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号)。
实验过程:
-
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;
-
-
no rows selected
-
-
SYS@proc>
-
SYS@proc> insert into aa values(1,'aa');
-
-
1 row created.
-
-
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;
-
-
FILE# DBABLK STATE
-
---------- ---------- ----------
-
7 128 1
-
7 129 1
-
7 130 1
-
7 131 3
-
7 131 1
-
7 144 1
-
7 145 1
-
7 146 1
-
7 147 1
-
7 148 1
-
7 149 1
-
-
FILE# DBABLK STATE
-
---------- ---------- ----------
-
7 150 1
-
7 151 1
-
7 152 1
-
7 153 1
-
7 154 1
-
7 155 1
-
7 156 1
-
7 157 1
-
7 158 1
-
7 159 1
-
- 21 rows selected.
于是尝试rollback,并清空buffer cache,再次插入是什么情况。
-
SYS@proc> rollback;
-
-
Rollback complete.
-
-
SYS@proc> alter system flush buffer_cache;
-
-
System altered.
-
-
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;
-
-
no rows selected
-
-
SYS@proc> insert into aa values(1,'aa');
-
-
1 row created.
-
-
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;
-
-
FILE# DBABLK STATE
-
---------- ---------- ----------
-
7 128 1
-
7 130 1
-
7 131 1
- 7 149 1
-
--------------------------------------------------------
-
DBA Ranges :
-
--------------------------------------------------------
-
0x01c00080 Length: 64 Offset: 0
-
-
0:Metadata 1:Metadata 2:Metadata 3:Metadata
-
4:unformatted 5:unformatted 6:unformatted 7:unformatted
-
8:unformatted 9:unformatted 10:unformatted 11:unformatted
-
12:unformatted 13:unformatted 14:unformatted 15:unformatted
-
16:75-100% free 17:75-100% free 18:75-100% free 19:75-100% free
-
20:75-100% free 21:75-100% free 22:75-100% free 23:75-100% free
-
24:75-100% free 25:75-100% free 26:75-100% free 27:75-100% free
-
28:75-100% free 29:75-100% free 30:75-100% free 31:75-100% free
-
32:unformatted 33:unformatted 34:unformatted 35:unformatted
-
36:unformatted 37:unformatted 38:unformatted 39:unformatted
-
40:unformatted 41:unformatted 42:unformatted 43:unformatted
-
44:unformatted 45:unformatted 46:unformatted 47:unformatted
-
48:unformatted 49:unformatted 50:unformatted 51:unformatted
-
52:unformatted 53:unformatted 54:unformatted 55:unformatted
-
56:unformatted 57:unformatted 58:unformatted 59:unformatted
-
60:unformatted 61:unformatted 62:unformatted 63:unformatted
-
--------------------------------------------------------
- End dump data blocks tsn: 23 file#: 7 minblk 128 maxblk 128
但是这里却有了另外一个问题,根据原先的提出“如果我向本例的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看看吧。
-
Extent Control Header
-
-----------------------------------------------------------------
-
Extent Header:: spare1: 0 spare2: 0 #extents: 1 #blocks: 128
-
last map 0x00000000 #maps: 0 offset: 2716
-
Highwater:: 0x01c000c0 ext#: 0 blk#: 64 ext size: 128
-
#blocks in seg. hdr's freelists: 0
-
#blocks below: 60
-
mapblk 0x00000000 offset: 0
-
Unlocked
-
--------------------------------------------------------
-
Low HighWater Mark :
-
Highwater:: 0x01c00084 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: 0x01c00080
-
Level 1 BMB for Low HWM block: 0x01c00080
-
--------------------------------------------------------
-
Segment Type: 1 nl2: 1 blksz: 8192 fbsz: 0
-
L2 Array start offset: 0x00001434
-
First Level 3 BMB: 0x00000000
-
L2 Hint for inserts: 0x01c00082
-
Last Level 1 BMB: 0x01c00081
-
Last Level II BMB: 0x01c00082
-
Last Level III BMB: 0x00000000
-
Map Header:: next 0x00000000 #extents: 1 obj#: 89427 flag: 0x10000000
-
Inc # 0
-
Extent Map
-
-----------------------------------------------------------------
-
0x01c00080 length: 128
-
-
Auxillary Map
-
--------------------------------------------------------
-
Extent 0 : L1 dba: 0x01c00080 Data dba: 0x01c00084
-
--------------------------------------------------------
-
-
Second Level Bitmap block DBAs
-
--------------------------------------------------------
-
DBA 1: 0x01c00082
-
- End dump data blocks tsn: 23 file#: 7 minblk 131 maxblk 131
其他资料:
插入一行数据格式的数据块个数是不固定的,有过5个,16个,32个,64个等。
插入一行数据格式化的数据块数量应该是和区大小以及高水位位置有一定关系吧,总之格式化数据块是按批进行的,具体一批是多少还不清楚。
在L1块中关于数据块的状态有7种格式:Unformat 75-100% 50-75% 25-50% 0-25% FULL Metadata