oracle中数据文件的描述

数据文件和重做日志文件是数据库中最重要的文件。

您的数据最终就是要存储在数据文件中。每个数据库都至少有一个相关的数据文件,通常还不止一个。最简单的“测试”数据库只有一个数据文件。其中用最简单的CREATE DATABASE命令根据默认设置创建了一个数据库,这个数据库中有两个数据文件,其中一个对应SYSTEM表空间(真正的Oracle数据字典),另一个对应SYSAUX表空间(在10g及以上版本中,非字典对象都存储在这个表空间中)。不过,所有实际的数据库都至少有3个数据文件;一个存储SYSTEM数据,一个存储SYSAUX数据,还有一个存储USER数据。

简要回顾文件系统类型之后,我们将讨论如何组织这些文件,以及文件中如何组织数据。要了解这些内容,需要知道什么是表空间(tablespace)、什么是段(segment)、什么是区段(extent),以及什么是块(block)。这些都是Oracle在数据库中存储对象所用的分配单位,稍后将详细介绍。

简要回顾文件系统机制

在Oracle中,可以用4种文件系统机制存储您的数据。这里强调了“您的数据”,是指您的数据字典、redo记录、undo记录、表、索引、LOB等,也就是您自己每天关心的数据。简单地讲,这包括:

a)“Cooked”操作系统(OS)文件系统:这些文件就像字处理文档一样放在文件系统中。在Windows 资源管理器中可以看到这些文件,在UNIX上,可以通过ls命令看到这些文件。可以使用简单的OS工具(如Windows上的xcopy或UNIX上的cp)来移动文件。从历史上看,Cooked OS文件一直是Oracle中存储数据的“最流行”的方法,不过我个人认为,随着ASM(稍后再详细说明)的引入,这种情况会有所改观。Cooked文件系统(“加工”文件系统或“熟”文件系统)通常也会缓存,这说明在您读写磁盘时,OS会为您缓存信息。

b)原始分区(raw partitions,也称裸分区):这不是文件,而是原始磁盘。不能用ls来查看;不能在Windows资源管理器中查看其内容。它们就是磁盘上的一些大扇区,上面没有任何文件系统。对Oracle来说,整个原始分区就是一个大文件。这与cooked文件系统不同,cooked文件系统上可能有几十个甚至数百个数据库数据文件。目前,只有极少数Oracle安装使用原始分区,因为原始分区的管理开销很大。原始分区不是缓冲设备,所完成的所有I/O都是直接I/O,对数据没有任何OS缓冲(不过,对于数据库来说,这通常是一个优点)。

c)自动存储管理(Automatic Storage Management,ASM):这是 Oracle 10g Release 1 的一个新特性(标准版和企业版都提供了这个特性)。ASM是专门为数据库设计的文件系统。可以简单地把它看作一个数据库文件系统。在这个文件系统上,不是把购物清单存储在文本文件中;这里只能存储与数据库相关的信息:您的表、索引、备份、控制文件、参数文件、重做日志、归档文件等。不过,即使是ASM,也同样存在着相应的数据文件;从概念上讲,数据库仍存储在文件中,不过现在的文件系统是ASM。ASM设计成可以在单机环境或者集群环境中工作。

d)集群文件系统:这个文件系统专用于RAC(集群)环境,看上去有些像由集群环境中多个节点(计算机)共享的cooked文件系统。传统的cooked文件系统只能由集群环境中的一台计算机使用。所以,尽管可以在集群中的多个节点之间使用NFS装载或Samba共享一个cooked文件系统(Samba与NFS类似,可以在Windows/UNIX环境之间共享磁盘),但这会导致一损俱损。如果安装有文件系统并提供共享的节点失败,这个文件系统都将不可用。Oracle集群文件系统(Oracle Cluster File System,OCFS)是Oracle在这个领域推出的一个新的文件系统,目前只能在Windows和Linux上使用。其他第三方开发商也提供了一些经认证的集群文件系统,也可以用于Oracle。集群文件系统让cooked文件系统的优点延伸到了集群环境中。

有意思的是,数据库可能包含来自上述所有文件系统中的文件,您不必只选其中的一个。在您的数据库中,可能部分数据存储在一个传统的cooked文件系统中,有些在原始分区上,有一些在ASM中,还有一些在集群文件系统中。这样就能很容易地切换技术,或者只是涉及一个新的文件系统,而不必把整个数据库都搬到这个文件系统中。现在,因为完整地讨论文件系统及其详细的属性超出了本书的范围,所以我们还是回过头来深入探讨Oracle文件类型。不论文件是存储在cooked文件系统、原始分区、ASM中,还是存储在集群文件系统中,以下概念都适用。

  Oracle数据库中的存储层次体系

数据库由一个或多个表空间构成。表空间(tablespace)是Oracle 中的一个逻辑存储容器,位于存储层次体系的顶层,包括一个或多个数据文件。这些文件可能是文件系统中的cooked文件、原始分区、ASM管理的数据库文件,或者是集群文件系统上的文件。表空间包含段,请看下面的介绍。
1. 段
现在开始分析存储层次体系,首先讨论段,这是表空间中主要的组织结构。段(segment)就是占用存储空间的数据库对象,如表、索引、回滚段等。创建表时,会创建一个表段。创建分区表时,则每个分区会创建一个段。创建索引时,就会创建一个索引段,依此类推。占用存储空间的每一个对象最后都会存储在一个段中,此外还有回滚段(rollback segment)、临时段(temporary segment)、聚簇段(cluster segment)、索引段(index segment)等。
注意    上面有这样一句话:“占用存储空间的每一个对象最后都会存储在一个段中”,这可能会把你搞糊涂。你会发现许多CREATE语句能创建多段的对象。之所以会产生困惑,原因是一条CREATE语句最后创建的对象可能包含0个、1个或多个段!例如,CREATE TABLE T ( x int primary key, y clob)就会创建4个段:一个是TABLE T的段,还有一个段对应索引(这个索引是为支持主键而创建的),另外还有两个CLOB段(一个CLOB段是LOB索引,另一个段是LOB数据本身)。与之不同,CREATE TABLE T ( x int, y date ) cluster MY_CLUSTER则不会创建任何段。第10章还会更深入地讨论这个概念。
2. 区段
段本身又由一个或多个区段组成。区段(extent)是文件中一个逻辑上连续分配的空间(一般来讲,文件本身在磁盘上并不是连续的;否则,根本就不需要消除磁盘碎片的工具了!)。另外,利用诸如独立磁盘冗余阵列(Redundant Array of Independent Disks,RAID)之类的磁盘技术,你可能会发现,一个文件不仅在一个磁盘上不连续,还有可能跨多个物理磁盘。每个段都至少有一个区段,有些对象可能还需要至少两个区段(回滚段就至少需要两个区段)。如果一个对象超出了其初始区段,就会请求再为它分配另一个区段。第二个区段不一定就在磁盘上第一个区段旁边,甚至有可能不在第一个区段所在的文件中分配。第二个区段可能与第一个区段相距甚远,但是区段内的空间总是文件中的一个逻辑连续空间。区段的大小可能不同,可以是一个Oracle数据块,也可以大到2 GB。
3. 块
区段又进一步由块组成。块(block)是Oracle中最小的空间分配单位
。数据行、索引条目或临时排序结果就存储在块中。通常Oracle从磁盘读写的就是块。Oracle中块的常见大小有4种:2 KB、4 KB、8 KB或16 KB(尽管在某些情况下32 KB也是允许的;但是操作系统可能对最大大小有限制)。
注意    有一点可能很多人都不知道:数据库的默认块大小不必是2的幂。2的幂只是一个常用的惯例。实际上,你完全可以创建块大小为5 KB、7 KB或n KB的数据库,这里n介于2~32 KB之间。不过,我还是建议你在实际中不要考虑这样做,块大小还是用2 KB、4 KB、8 KB或16 KB比较好。

一个段由一个或多个区段组成,区段则由连续分配的一些块组成。从Oracle9i Release 1起,数据库中最多可以有6种不同的块大小(block size)。

注意    之所以引入这个特性,即一个数据库中允许有多种块大小,目的是为了可以在更多的情况下使用可传输的表空间。如果能传输表空间,DBA就能从一个数据库移动或复制格式化的数据文件,把它放在另一个数据库中,例如,可以从一个联机事务处理(Online Transaction Processing,OLTP)数据库中把所有表和索引复制到一个数据仓库(Data Warehouse,DW)中。不过,在许多情况下,OLTP数据库使用的块大小可能很小,如2 KB或4 KB,而DW使用的块大小可能很大(8 KB或16 KB)。如果一个数据库中不支持多种块大小,就无法传输这些信息。有多种块大小的表空间主要用于传输表空间,一般没有其他用途。

数据库还有一个默认的块大小,即执行CREATE DATABASE命令时初始化文件中指定的大小。SYSTEM表空间总是使用这个默认块大小,不过你完全可以按非默认块大小(2 KB、4 KB、8 KB或16 KB)创建其他表空间,如果操作系统允许,还可以使用32 KB的块大小。当且仅当创建数据库时指定了一个非标准的块大小(不是2的幂)时,才会有6种不同的块大小。因此,在实际中,数据库最多有5种不同的块大小:默认大小和另外4种非默认的块大小。

在所有给定的表空间内部,块大小都是一致的,这说明,一个表空间中的所有块大小都相同。对于一个多段对象,如一个包含LOB列的表,可能每个段在不同的表空间中,而这些表空间分别有不同的块大小,但是任何给定段(包含在表空间中)都由相同大小的块组成。无论大小如何,所有块格式都一样,
块首部(block header)包含块类型的有关信息(表块、索引块等)、块上发生的活动事务和过去事务的相关信息(仅事务管理的块有此信息,例如临时排序块就没有事务信息),以及块在磁盘上的地址(位置)。块中接下来两部分是表目录和行目录,最常见的数据库块中(即堆组织表的数据块)都有这两部分。以后将更详细地介绍数据库表类型,不过,现在知道大多数表都是这种类型就足够了。如果有表目录(table directory),则其中会包含把行存储在这个块上的表的有关信息(可能一个块上存储了多个表的数据)。行目录(row directory)包含块中行的描述信息。这是一个指针数组,指向块中数据部分中的行。块中的这3部分统称为块开销(block overhead),这部分空间并不用于存放数据,而是由Oracle用来管理块本身。块中余下的两部分就很清楚了:块上可能有一个空闲空间(free space),通常还会有一个目前已经存放数据的已用空间(used space)。

从以上介绍可以知道,段由区段组成,区段由块组成,对段有了大致的了解后,下面再来更深入地分析表空间,然后说明文件在这个存储层次体系中的位置。

4. 表空间

前面已经提到,表空间是一个容器,其中包含有段。每个段都只属于一个表空间。一个表空间中可能有多个段。一个给定段的所有区段都在与段相关联的表空间中。段绝对不会跨越表空间边界。表空间本身可以有一个或多个相关的数据文件。表空间中给定段的一个区段完全包含在一个数据文件中。不过,段可以有来自多个不同数据文件的区段
表空间是Oracle中的逻辑存储容器。作为开发人员,我们会在表空间中创建段,而绝对不会深入到原始的“文件级”。我们可不希望在一个特定的文件中分配区段(当然这也是可以的,但我们一般都不会这么做)。相反,我们会在表空间中创建对象,余下的工作都由Oracle负责。如果将来某个时刻DBA决定在磁盘上移动数据文件,从而使I/O分布得更均匀,这对我们来说没有任何关系,它根本不会影响我们的处理。

5. 存储层次体系小结

总结一下,Oracle中的存储层次体系如下:

(1) 数据库由一个或多个表空间组成。

(2) 表空间由一个或多个数据文件组成。这些文件可以是文件系统中的cooked文件、原始分区、ASM管理的数据库文件,或集群文件系统上的文件。表空间包含段。

(3) 段(TABLE、INDEX等)由一个或多个区段组成。段在表空间中,但是可以包含这个表空间中多个数据文件中的数据。

(4) 区段是磁盘上一组逻辑连续的块。区段只在一个表空间中,而且总是在该表空间内的一个文件中。

(5) 块是数据库中最小的分配单位,也是数据库使用的最小I/O单位。

字典管理和本地管理的表空间

在继续讨论之前,我们再来看看关于表空间的一个问题:在表空间中如何管理区段。在Oracle 8.1.5之前,表空间中管理区段的分配只有一种方法:字典管理的表空间(dictionary-managed tablespace)。也就是说,表空间中的空间在数据字典表中管理,这与管理账户数据(利用DEBIT和CREDIT表)的方法是一样的。借方有已经分配给对象的所有区段。贷方是所有可用的自由区段。如果一个对象需要另一个区段,就会向系统“申请”。然后Oracle访问其数据字典表,运行一些查询,查找到空间(也许找不到),然后更新一个表中的一行(或者从表中将这一行删除),再向另一个表插入一行。Oracle管理空间与你编写应用可谓异曲同工:同样是要修改数据以及移动数据。

为了得到额外的空间而在后台代表你执行的SQL称为递归SQL(recursive SQL)。你的SQL INSERT语句会导致执行其他递归SQL来得到更多空间。如果频繁地执行这种递归SQL,开销可能相当大。对数据字典的这种更新必须是串行的;它们不能同时进行,所以要尽量避免。

在Oracle的早期版本中,可以看到,这种空间管理问题(递归SQL开销)在“临时表空间”中最常见(这还不是“真正的”临时表空间,真正的临时表空间是通过CREATE TEMPORARY TABLESPACE命令创建的)。空间会频繁地分配(从字典表删除,而插入到另一个表)和撤销(把刚移动的行再移回原来的位置)。这些操作必须串行执行,这就大大削弱了并发性,而增加了等待时间。在7.3版本中,Oracle引入了一个真正的临时表空间(true temporary tablespace)概念,这是一个新的表空间类型,专门用于存储临时数据,从而帮助缓解这个问题。在引入这个特殊的表空间类型之前,临时数据与永久数据在同样的表空间中管理,处理方式也与永久数据一样。

而临时表空间则不同,你不能在其中创建自己的永久对象。实际上根本的区别只有这一条;空间还是在数据字典表中管理。不过,一旦在临时表空间中分配了一个区段,系统就会一直持有(也就是说,不会把空间交回)。下一次有人出于某种目的在临时表空间中请求空间时,Oracle会在其内部的已分配区段列表中查找已经分配的区段。如果找到,就会直接重用,否则还是用老办法来分配一个区段。采用这种方式,一旦数据库启动,并运行一段时间,临时段看上去就好像满了,但是实际上只是“已分配”。里面都是空闲区段,它们的管理完全不同。当有人需要临时空间时,Oracle会在内存中的数据结构里查找空间,而不是执行代价昂贵的递归SQL。

在Oracle 8.1.5及以后版本中,Oracle在减少这种空间管理开销方面又前进了一步。它引入了一个本地管理表空间(locally-managed tablespace )概念,而不是字典管理表空间。与Oracle 7.3中对临时表空间的管理一样,本地空间管理采用了同样的办法来管理所有表空间:这样就无需使用数据字典来管理表空间中的空间。对于本地管理表空间,会使用每个数据文件中存储的一个位图来管理区段。现在要得到一个区段,系统所做的只是在位图中将某一位设置为1。要释放空间,系统再把这一位设置为0。与使用字典管理的表空间相比,这样分配和释放空间就相当快。为了处理跨所有表空间的空间请求,我们不再需要在数据库级串行完成这些耗时的操作,相反,只需在表空间级串行执行一个速度相当快的操作。本地管理的表空间还有另外一些很好的特点,如可以保证区段的大小统一,不过这一点DBA更关心。

再往后,则只应使用本地管理的表空间作为存储管理方法。实际上,在Oracle9i及以上版本中,如果使用数据库配置助手(database configuration assistant,DBCA)创建一个数据库,它就会创建一个SYSTEM作为本地管理的表空间,如果SYSTEM是本地管理的,那么该数据库中所有其他表空间也会是本地管理的,而且遗留的字典管理方法将无法工作。如果数据库中的SYSTEM是本地管理的表空间,并不是说这样的数据库中不支持字典管理的表空间,而是说其中根本无法创建字典管理的表空间:

这是一个正面的副作用,因为这样可以杜绝你使用遗留的存储机制,要知道它的效率相对较低,而且很可能导致碎片。本地管理的表空间除了在空间分配和撤销方面效率更高以外,还可以避免出现表空间碎片,这正是以本地管理表空间的方式分配和撤销空间的一个副作用

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值