ORACLE块的分析

(一)
一直以来对“块”的概念总是含混不清,从字面意义理解,只知道这是ORACLE存放数据的最小单位,然而它的内部世界如何呢,本人打算从今天开始连载几篇文档,对它进行深度分析。
通过很多文档、资料,了解到了数据库基本结构鱼刺图:
基本上每个对象对应一个段( Segment),只有分区对应多个段,这里的对象包括table,index,partition等等,段可以跨越多个数据文件。
每个段又有多个区(extent)来组成,这些区不能跨越多个数据文件,同时在系统使用过程中自动扩展。
最后是块(block),所有的数据都是存放在块中。为了适应操作系统,每个块在创建数据库的时候默认了一个大小,这个大小一般是8K,同时在9I及其以 后的版本中增加了不同大小的块参数,这将在以后的实验中体现。先说说这个8K大小的块,一般来说,为了使得oracle运行读写数据文件的时候有一个合理 的吞吐量,这里的块大小,都跟操作系统块大小设为整数倍,例如ntfs格式化的磁盘文件,每个物理块大小为4,这里oracle的块大小为8,即是代表每 读取一个oracle块,其实物理上也就是读取了两个操作系统块。 这里主要指的是数据文件存放在块设备上,在实际的生产环境中,大部分情况都是将数据库安装在裸设备(RAW)也叫做原始分区之上。关于RAW将在以后进行 讲解。

通过上面这段文字,我们可以了解到ORACLE基本的存储结构,下一篇将针对块的大小与存放数据大小来做实验。
(二)
上一节了解到了ORACLE的存储结构,这节讲一讲块的大小与数据存放之间的关系。
大家都知道了在ORACLE环境中,所有的对象都是存放在块中,这个块大小与存放的记录之间到底存在怎样的关系呢?
做一个实验看看:
1.创建一个表空间test

create tablespace test datafile 'F:\oracle\product\10.1.0\oradata\liweiwei\test.dbf' size 100M;

2.创建一个用户并授权,连接

create user test identified by test default tablespace test;
grant connect,resource to test;
connect test/test@liweiwei

3.创建一个表

create table test.t1(a1 number,a2 number);

4.检查段,可以发现在这个视图中出现了名称为T的段,段类型为TABLE,这个段里面分配了1个区,其中包含8个块,大小为64K字节。

select segment_name, blocks, extents, bytes, segment_type, tablespace_name
from dba_segments
where owner = 'TEST';



[img]http://dl.iteye.com/upload/attachment/376444/afc8a4a4-f7d7-3967-a164-9a1917a65c7b.png[/img]

5.检查区,可以发现在这个视图中出现了一个区,区号为0,包含8个块,大小为64K字节。

select segment_name,segment_type,extent_id,blocks,bytes from dba_extents where owner='TEST';



[img]http://dl.iteye.com/upload/attachment/376446/1d12268b-b84e-37da-a080-22a92b3a41d1.png[/img]
6.查询t1表所属的Object id,检查块,可以发现这里没有载入到内存的块,由此断定,在数据未写入的时候,内存中并没有存放数据的块。

select obj# from obj$ where name='T1';



[img]http://dl.iteye.com/upload/attachment/376554/f0034ab9-8778-3417-bb06-d650b7c666d7.png[/img]


select file#,block#,class#,status,xnc,objd from v$bh where objd=49685

没有数据。
7.插入10行数据,进行测试。

declare
i number;
begin
for i in 1 .. 10 loop
execute immediate 'insert into test.t1 values(:x,:y)'
using i, i;
end loop;
end;

8.再次查看v$bh视图,检查内存中是否使用到了块。

select file#,block#,class#,status,xnc,objd from v$bh where objd=49685



[img]http://dl.iteye.com/upload/attachment/376558/c60dc993-59a2-33e8-8ef2-c9360f4433c0.png[/img]

果然出现了数据,说明在数据插入的表的时候在内存中已经载入了分配的块,同时在这些块中写入了数据,这里占用了两个块,块号分别为58729,58730,其中我们可以根据CLASS#来判断出他们属于不同类型.
(三)
这一节紧接着上一节来说。
上一节通过实验,我们了解到,块的创建和读取流程,不过只是针对一个会话的,现在我们来看看在一个会话中插入数据之后,同时在另外一个会话查询数据,这样的情况会对块有什么影响。
打开一个新的会话, 然后执行如下命令:
查询表,由于插入数据的事务没有提交,这里在另外的会话中就看不到任何数据,深深体现了ORACLE的多版本一致性
select * from t1;

未选定行
查询视图v$bh,看是否有了变化
select file#,block#,class#,status,xnc,objd from v$bh where objd=49685;


[img]http://dl.iteye.com/upload/attachment/376560/f0720d91-5f49-3891-86e3-5cd814c84a59.png[/img]

果然和上一节查询出来的结果不同,多了红色字体标识出来的两行,大家可以看到这两行的STATUS字段值为cr,什么是cr呢?它是Consistency Read(一致性读取)的缩写。从这里可以看出58730这个块被两个会话进行了操作。
在第一个会话中回滚事务会发生什么呢?看下面的操作:
会话1:执行rollback
SQL> rollback;
回退已完成。
再次查询v$bh视图,看看什么情况
select file#,block#,class#,status,xnc,objd from v$bh where objd=49684;


[img]http://dl.iteye.com/upload/attachment/376563/f07966d8-3404-306c-b607-6c60039542d0.png[/img]

结果还是一样,说明在事务回滚之后,块还是处于一致读取的状态。
(四)
我们继续上一节的话题。
关闭数据库实例
[quote]
SQL> shutdown immediate;
数据库已经关闭。
已经卸载数据库。
ORACLE 例程已经关闭。
SQL> startup;
ORACLE 例程已经启动。

Total System Global Area 171966464 bytes
Fixed Size 787988 bytes
Variable Size 145488364 bytes
Database Buffers 25165824 bytes
Redo Buffers 524288 bytes
数据库装载完毕。
数据库已经打开。
[/quote]
检查v$bh视图
select file#,block#,class#,status,xnc,objd from v$bh where objd=11038; 

未选定行
说明在没有进行块中数据的相关操作的时候,并没有从物理文件中提取块到内存。
执行查询或者插入、更新的SQL语句
[quote]SQL> insert into test.t values (200,200);
已创建 1 行。 [/quote]
再次检查v$bh视图
SQL> select file#,block#,class#,status,xnc,objd from v$bh where objd=49685; 

[img]http://dl.iteye.com/upload/attachment/376571/32b0ccc9-3344-35f0-ae8e-705a09d8c318.png[/img]

总结:在没有进行物理I/O的时候,v$bh视图中不会出现相关的块信息,同时证明此视图中存放的乃是数据文件块放到内存中的“块”信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值