oracle 存储过程_Oracle Truncate table原理:ASSM的三级位图实践解析

更新时间:2020-10-13    来源:php基础    手机版     字体:

【www.bbyears.com--php基础】

assm三级位图可以说是dba的基础技能知识了,这里用测试的方法验证下三级位图的原理。

1.建立实验环境所需要的表

SQL> create tablespace a1 datafile "/oracle/app/oracle/oradata/ora11/a1.dbf" size 20m;   
Tablespace created.                                                                   
SQL> create user a1 identified by a1 default tablespace a1;                             
User created.                                                                         
SQL> grant dba to a1;                                                         
Grant succeeded.                                                                      
SQL> connect a1/a1                                                            
Connected.   
SQL> create table a as select * from dba_tables;                    
Table created.

实验环境建立完成之后,就需要摸清楚我们的这个段A的位图及数据块分布情况,我们不直接从视图里面查,这里我们考虑需要通过bbed的方式从数据块中获取位图及数据块分布情况。

2.段头块/L3位图块指向了哪些L2位图块

段由哪些区间构成?这个信息我们需要从段头块中获取出来。当你创建一个段后,即使你没有往里面插入任何数据,系统也是会预先分配一些区给你的。所以段头块是那个块,我们可以通过dba_segments查询出来。就算truncate了这个段,我们仍然能够从dba_segments中查询到段头的信息。

SQL> select HEADER_FILE,HEADER_BLOCK from dba_segments where SEGMENT_NAME="A" and owner="A1";
HEADER_FILE HEADER_BLOCK
----------- ------------
          5          130

找到了段头块,就可以用bbed挖掘下信息。

BBED> set filename "/oracle/app/oracle/oradata/ora11/a1.dbf"
        FILENAME        /oracle/app/oracle/oradata/ora11/a1.dbf
BBED> set block 130
        BLOCK#          130
BBED> dump /v offset 0 count 20
 File: /oracle/app/oracle/oradata/ora11/a1.dbf (0)
 Block: 130     Offsets:    0 to   19  Dba:0x00000000
-------------------------------------------------------
 23a20000 82004001 d8321400 00000104 l #.@.....
 848d0000                            l ....
                       l ....
这里我们可以看到段头块的第一个offset是23。那么我们的段头块指向的L2位图块在offset 5192的位置。这里请记住段头块的标示是23。

BBED> dump /v offset 5192 count 100
 File: /oracle/app/oracle/oradata/ora11/a1.dbf (0)
 Block: 130     Offsets: 5192 to 5291  Dba:0x00000000
-------------------------------------------------------
 81004001 00000000 00000000 00000000 l ..@.............
 00000000 00000000 00000000 00000000 l ................
 00000000 00000000 00000000 00000000 l ................
 00000000 00000000 00000000 00000000 l ................
 00000000 00000000 00000000 00000000 l ................
 00000000 00000000 00000000 00000000 l ................
 00000000                            l ....

从这里我们既可以找到我们的L2位图块,81004001,这里只有1个L2块,因为后面都是00000000(空),因为涉及到操作系统字节序的问题,这里需要转换换成01400081。转换后我们可以使用下列查询找到文件号和块号。


SQL> select dbms_utility.data_block_address_file(to_number("01400081","xxxxxxxx")) as fileno,dbms_utility.data_block_address_block(to_number("01400081","xxxxxxxx")) as blockno from dual;

    FILENO    BLOCKNO

---------- ----------
5
         5        129

3.L2位图块指向了哪些L1位图块

接下来我们可以继续读我们的L2位图块来寻找我们的L1位图块。可以看到L2的第一个offset是21。请记住L2位图块的标示是21。

BBED> set block 129
        BLOCK#          129

BBED> dump /v offset 0 count 20
 File: /oracle/app/oracle/oradata/ora11/a1.dbf (0)
 Block: 129     Offsets:    0 to   19  Dba:0x00000000
-------------------------------------------------------
 21a20000 81004001 d4321400 00000604 l !.@.....
 48a10000                            l H


L2指向L1数据块的位置从offset 116开始。到哪儿结束需要看后面有没有00000000(空)

BBED> dump /v offset 116 count 100
 File: /oracle/app/oracle/oradata/ora11/a1.dbf (0)
 Block: 129     Offsets:  116 to  215  Dba:0x00000000
-------------------------------------------------------
 80004001 01000100 90004001 01000100 l ..@.......@.....
 a0004001 01000100 b0004001 01000100 l ........
 c0004001 01000100 d0004001 01000100 l ........
 e0004001 05000100 00000000 00000000 l ............
 00000000 00000000 00000000 00000000 l ................
 00000000 00000000 00000000 00000000 l ................
 00000000                            l ....


从dump出来的地方我们来看,前面是一个地址,后面跟着是01000100,比较规律,大概7组之后就变成00000000(空)了。 跟上面一样因为字节序的问题,这里我们需要将80004001转换成01400080。然后我们通过下列查询得到了区块的位置。而后面的01000100,前面的01则这个L1下面的块全部填满,无空数据块,后面的01则代表这个块是instance 1产生的。而最后的一个05000100,05则代表着这个L1下面还有空块,可以插入。而后面的01我们说过代表着是instance。如果这个系统是个rac的系统,节点2也插入了数据,那么这里就会显示05000200。

SQL> select dbms_utility.data_block_address_file(to_number("01400080","xxxxxxxx")) as fileno,dbms_utility.data_block_address_block(to_number("01400080","xxxxxxxx")) as blockno from dual
     union
     select dbms_utility.data_block_address_file(to_number("01400090","xxxxxxxx")) as fileno,dbms_utility.data_block_address_block(to_number("01400090","xxxxxxxx")) as blockno from dual
     union
     select dbms_utility.data_block_address_file(to_number("014000a0","xxxxxxxx")) as fileno,dbms_utility.data_block_address_block(to_number("014000a0","xxxxxxxx")) as blockno from dual
     union
     select dbms_utility.data_block_address_file(to_number("014000b0","xxxxxxxx")) as fileno,dbms_utility.data_block_address_block(to_number("014000b0","xxxxxxxx")) as blockno from dual
     union
     select dbms_utility.data_block_address_file(to_number("014000c0","xxxxxxxx")) as fileno,dbms_utility.data_block_address_block(to_number("014000c0","xxxxxxxx")) as blockno from dual
     union
     select dbms_utility.data_block_address_file(to_number("014000d0","xxxxxxxx")) as fileno,dbms_utility.data_block_address_block(to_number("014000d0","xxxxxxxx")) as blockno from dual
     union
     select dbms_utility.data_block_address_file(to_number("014000e0","xxxxxxxx")) as fileno,dbms_utility.data_block_address_block(to_number("014000e0","xxxxxxxx")) as blockno from dual;
    FILENO    BLOCKNO
---------- ----------
         5        128
         5        144
         5        160
         5        176
         5        192
         5        208
         5        224

7 rows selected.


通过上述查询,我们找到了7个L1块的信息。
4.L1位图块指向了哪些数据块
前面我们查到了我们的L2块上指向的L1块,并且清楚的知道哪个L1下面是满的,哪个L1下面还有空闲块。我们就从拿最后一个有空闲块的L1位图块进行分析。

BBED> set block 224
        BLOCK#          224

BBED> dump /v offset 0 count 10
 File: /oracle/app/oracle/oradata/ora11/a1.dbf (0)
 Block: 224     Offsets:    0 to    9  Dba:0x00000000
-------------------------------------------------------
 20a20000 e0004001 d432              l  .@.
<16 bytes per line>


可以看到L1的第一个offset是20。请记住L1位图块的标示是20。
L1指向数据块的位置从offset 204开始。到哪儿结束需要看后面有没有00000000(空)

BBED> dump /v offset 204 count 80
 File: /oracle/app/oracle/oradata/ora11/a1.dbf (0)
 Block: 224     Offsets:  204 to  283  Dba:0x00000000
-------------------------------------------------------
 e0004001 08000000 00000000 e8004001 l ........08000000 08000000 00000000 00000000 l ................
 00000000 00000000 00000000 00000000 l ................
 00000000 00000000 00000000 00000000 l ................
 00000000 00000000 00000000 00000000 l ................


大家可以看到这里的值是e0004001,08000000,00000000,下一组值是e8004001,08000000,08000000,然后面就是00000000(空)。
这两个的意思是告诉我们L1指向数据块的起始位置,比如e0004001,就是文件5,块224,也就是它自己本身。08000000就代表着这个块后面的连续7个块都是的。而e8004001,08000000,08000000,就是文件5,块232,08000000就代表着这个块后面的连续7个块也是的。而最后一个08000000则代表着offset,这里我们可以不用去管它。所以这里我们就能够知道我们的L1块下面具体的数据块有:
224(它本身),225,226,227,228,229,230,231,232,233,234,235,236,237,238,239。来用下列语句查证一下。

SQL> select distinct dbms_rowid.rowid_block_number(rowid) from a order by 1


可以看到223后面直接就是225,直接此处跳空,这是因为我们的224是L1位图块,后面紧跟着我们刚刚说的225,226,227,228,229,230,231,232,233。但是问题是,这里看不到后面的234到239?这是因为234到239还是空闲没有格式化过的块,但是它已经被L1锁定了。那么我们的L1能不能看到这些情况呢?我们可以观察offset 396。

BBED> dump /v offset 396 count 50
 File: /oracle/app/oracle/oradata/ora11/a1.dbf (0)
 Block: 224     Offsets:  396 to  445  Dba:0x00000000
-------------------------------------------------------
 11111111 11000000 00000000 00000000 l ................
 00000000 00000000 00000000 00000000 l ................
 00000000 00000000 00000000 00000000 l ................
 0000                                l ..

这里可以看到的是11111111,11000000。那么这个代表什么意思呢?如果这个块是full的话,就是1,是unformatted的话就是0,正好和我们前面看到的吻合。

本文来源:http://www.bbyears.com/jiaocheng/104429.html