(一)
一直以来对“块”的概念总是含混不清,从字面意义理解,只知道这是ORACLE存放数据的最小单位,然而它的内部世界如何呢,本人打算从今天开始连载几篇文档,对它进行深度分析。
通过很多文档、资料,了解到了数据库基本结构鱼刺图:
基本上每个对象对应一个段( Segment),只有分区对应多个段,这里的对象包括table,index,partition等等,段可以跨越多个数据文件。
每个段又有多个区(extent)来组成,这些区不能跨越多个数据文件,同时在系统使用过程中自动扩展。
最后是块(block),所有的数据都是存放在块中。为了适应操作系统,每个块在创建数据库的时候默认了一个大小,这个大小一般是8K,同时在9I及其以 后的版本中增加了不同大小的块参数,这将在以后的实验中体现。先说说这个8K大小的块,一般来说,为了使得oracle运行读写数据文件的时候有一个合理 的吞吐量,这里的块大小,都跟操作系统块大小设为整数倍,例如ntfs格式化的磁盘文件,每个物理块大小为4,这里oracle的块大小为8,即是代表每 读取一个oracle块,其实物理上也就是读取了两个操作系统块。 这里主要指的是数据文件存放在块设备上,在实际的生产环境中,大部分情况都是将数据库安装在裸设备(RAW)也叫做原始分区之上。关于RAW将在以后进行 讲解。
通过上面这段文字,我们可以了解到ORACLE基本的存储结构,下一篇将针对块的大小与存放数据大小来做实验。
(二)
上一节了解到了ORACLE的存储结构,这节讲一讲块的大小与数据存放之间的关系。
大家都知道了在ORACLE环境中,所有的对象都是存放在块中,这个块大小与存放的记录之间到底存在怎样的关系呢?
做一个实验看看:
1.创建一个表空间test
2.创建一个用户并授权,连接
3.创建一个表
4.检查段,可以发现在这个视图中出现了名称为T的段,段类型为TABLE,这个段里面分配了1个区,其中包含8个块,大小为64K字节。
[img]http://dl.iteye.com/upload/attachment/376444/afc8a4a4-f7d7-3967-a164-9a1917a65c7b.png[/img]
5.检查区,可以发现在这个视图中出现了一个区,区号为0,包含8个块,大小为64K字节。
[img]http://dl.iteye.com/upload/attachment/376446/1d12268b-b84e-37da-a080-22a92b3a41d1.png[/img]
6.查询t1表所属的Object id,检查块,可以发现这里没有载入到内存的块,由此断定,在数据未写入的时候,内存中并没有存放数据的块。
[img]http://dl.iteye.com/upload/attachment/376554/f0034ab9-8778-3417-bb06-d650b7c666d7.png[/img]
没有数据。
7.插入10行数据,进行测试。
8.再次查看v$bh视图,检查内存中是否使用到了块。
[img]http://dl.iteye.com/upload/attachment/376558/c60dc993-59a2-33e8-8ef2-c9360f4433c0.png[/img]
果然出现了数据,说明在数据插入的表的时候在内存中已经载入了分配的块,同时在这些块中写入了数据,这里占用了两个块,块号分别为58729,58730,其中我们可以根据CLASS#来判断出他们属于不同类型.
(三)
这一节紧接着上一节来说。
上一节通过实验,我们了解到,块的创建和读取流程,不过只是针对一个会话的,现在我们来看看在一个会话中插入数据之后,同时在另外一个会话查询数据,这样的情况会对块有什么影响。
打开一个新的会话, 然后执行如下命令:
查询表,由于插入数据的事务没有提交,这里在另外的会话中就看不到任何数据,深深体现了ORACLE的多版本一致性
未选定行
查询视图v$bh,看是否有了变化
[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视图,看看什么情况
[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视图
未选定行
说明在没有进行块中数据的相关操作的时候,并没有从物理文件中提取块到内存。
执行查询或者插入、更新的SQL语句
[quote]SQL> insert into test.t values (200,200);
已创建 1 行。 [/quote]
再次检查v$bh视图
[img]http://dl.iteye.com/upload/attachment/376571/32b0ccc9-3344-35f0-ae8e-705a09d8c318.png[/img]
总结:在没有进行物理I/O的时候,v$bh视图中不会出现相关的块信息,同时证明此视图中存放的乃是数据文件块放到内存中的“块”信息。
一直以来对“块”的概念总是含混不清,从字面意义理解,只知道这是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视图中不会出现相关的块信息,同时证明此视图中存放的乃是数据文件块放到内存中的“块”信息。