OracleDB常用操作实验.docx
《OracleDB常用操作实验.docx》由会员分享,可在线阅读,更多相关《OracleDB常用操作实验.docx(85页珍藏版)》请在冰豆网上搜索。
OracleDB常用操作实验
实验一插入时寻找空闲块的步骤篇(ASSM表空间)
服务器进程寻找空闲块的步骤:
在ASSM表空间中,执行Insert声明时,Oracle是如何为声明分配可用块的?
以前已经有网友论证,在ASSM中,可用块的管理,由L3、L2和L1三级位图块实现。
具体的步骤就是,先通过数据字典找到段头,而段头其实就是表的第一个L3块,在其中寻找L2。
根据执行插入声明的服务器进程的PID,计算出一个随机HASH值,根据此HASH值,在L2中找到一个L1。
再根据服务器进程的PID,在L1中查找一个可用的数据块,并在其中插入新行。
具体的步骤如下:
步1:
我的实验环境如下:
块大小:
8K;区大小40K;实验表现占5个区;
假设现在用户端发来命令如下:
Insertintonew01_jj_1values(1,’a’);
首先,对于new01_jj_1,数据库并不理解这是什么,Oracle首先要去查询数据字典表,了解这一串字母的具体意义,例如,Oracle要确定这是一个视图、同义词,或是一个表等等,这些操作,就是递归操作,我们只拣和我们今天的论题相关的说,Oracle要先查找seg$数据字典表,找出段头的文件号和块号,我们将这一步操作化为对基于seg$数据字典表的视图:
Dba_segments的操作:
SQL>selectheader_block,header_file,segment_typefromdba_segmentswheresegment_name='NEW01_JJ_1';
HEADER_BLOCKHEADER_FILESEGMENT_TYPE
-----------------------------------------
11 9TABLE
步2:
根据上面的显示结果可知,段头是在9号文件的第11号块,段头是第一个L3块,在L3中保存着L2块的地址,L2块保存着L1块的地址,L1块保存着数据块的地址。
所以想查找数据库的第一步,就是要先找到L3块,并在其中搜索可用的L2块,下面我们转储表的第一个L3块,即段头:
9号文件11号块,然后在其中搜索可用的L2块。
转储命令如下:
SQL>altersystemdumpdatafile9block11;
系统已更改。
转储结果如下:
***2008-02-1513:
46:
50.562
***SERVICENAMESYS$USERS)2008-02-1513:
46:
50.515
***SESSIONID206.4)2008-02-1513:
46:
50.515
Startdumpdatablockstsn:
11file#:
9minblk11maxblk11
buffertsn:
11rdba:
0x0240000b(9/11)
scn:
0x0000.001e0767seq:
0x01flg:
0x04tail:
0x07672301
frmt:
0x02chkval:
0x604atype:
0x23=PAGETABLESEGMENTHEADER
ExtentControlHeader
-----------------------------------------------------------------
ExtentHeader:
:
spare1:
0 spare2:
0 #extents:
5 #blocks:
25
lastmap 0x00000000 #maps:
0 offset:
2716
Highwater:
:
0x02400027 ext#:
4 blk#:
5 extsize:
5
#blocksinseg.hdr'sfreelists:
0
#blocksbelow:
21
mapblk 0x00000000 offset:
4
Unlocked
--------------------------------------------------------
LowHighWaterMark:
Highwater:
:
0x02400027 ext#:
4 blk#:
5 extsize:
5
#blocksinseg.hdr'sfreelists:
0
#blocksbelow:
21
mapblk 0x00000000 offset:
4
Level1BMBforHighHWMblock:
0x0240001d
Level1BMBforLowHWMblock:
0x0240001d
--------------------------------------------------------
SegmentType:
1nl2:
1 blksz:
8192 fbsz:
0
L2Arraystartoffset:
0x00001434
FirstLevel3BMB:
0x00000000
L2Hintforinserts:
0x0240000a
LastLevel1BMB:
0x0240001d
LastLevelIIBMB:
0x0240000a
LastLevelIIIBMB:
0x00000000
MapHeader:
:
next 0x00000000 #extents:
5 obj#:
52176 flag:
0x10000000
Inc#0
ExtentMap
-----------------------------------------------------------------
0x02400009 length:
5
0x0240000e length:
5
0x02400018 length:
5
0x0240001d length:
5
0x02400022 length:
5
AuxillaryMap
--------------------------------------------------------
Extent0 :
L1dba:
0x02400009Datadba:
0x0240000c
Extent1 :
L1dba:
0x02400009Datadba:
0x0240000e
Extent2 :
L1dba:
0x02400009Datadba:
0x02400018
Extent3 :
L1dba:
0x0240001dDatadba:
0x0240001e
Extent4 :
L1dba:
0x0240001dDatadba:
0x02400022
--------------------------------------------------------
SecondLevelBitmapblockDBAs
--------------------------------------------------------
DBA1:
0x0240000a
Enddumpdatablockstsn:
11file#:
9minblk11maxblk11
查看上面的信息,可知现在表New01_jj_1表中只有一个L2块,即9号文件第10号块。
将来随着表的增大,L1块的增多,L2块也会逐步增多。
那么,在L3中记录的L2也会随之增多,如何在众多L2块中快速找到一个可用的L2块呢?
Oracle专门增设了一个L2Hintforinserts,此处的值为0x0240000a,即第9号文件10号块。
我们可以直接根据L2Hintforinserts中的指示,找出可用的L2块,此处为第9号文件10号块,这就是在L3中查找L2的步骤,下面,我们转储L2,并在其中查找L1块。
步3:
转储L2块9号文件10号块:
SQL>altersystemdumpdatafile9block10;
系统已更改。
***2008-02-1513:
52:
03.359
Startdumpdatablockstsn:
11file#:
9minblk10maxblk10
buffertsn:
11rdba:
0x0240000a(9/10)
scn:
0x0000.001e0767seq:
0x01flg:
0x04tail:
0x07672101
frmt:
0x02chkval:
0x4cfbtype:
0x21=SECONDLEVELBITMAPBLOCK
DumpofSecondLevelBitmapBlock
number:
2 nfree:
1 ffree:
1 pdba:
0x0240000b
Inc#:
0Objd:
52176
opcode:
0
xid:
L1Ranges:
--------------------------------------------------------
0x02400009 Free:
1Inst:
1
0x0240001d Free:
3Inst:
1
--------------------------------------------------------
Enddumpdatablockstsn:
11file#:
9minblk10maxblk10
这里我们看到L2块中有两个L1块分别是9号块和29号块,到这一步,Oracle如何在L2中选择L1?
为了提高插入的并行度,这里将根据完成插入操作服务器进程的PID,计算出一个Hash值,根据此Hash值在多个L1中选择一个。
也就是在多个L1中根据进程PID随机选择一个。
此处要注意的是,高高水点(不是输入错误,高水点在ASSM中有两个:
低高水点和高高水点)之后的块不在选择范围内。
如果从两个会话中插入,Oracle会尽量将这两个进程分配到两个L1块中。
假设,这里选择了29号,我们再来转储它。
步4:
SQL>altersystemdumpdatafile9block29;
系统已更改。
***2008-02-1514:
00:
26.078
Startdumpdatablockstsn:
11file#:
9minblk29maxblk29
buffertsn:
11rdba:
0x0240001d(9/29)
scn:
0x000