2.6 Oracle逻辑结构
Oracle数据库管理与维护实战
Oracle逻辑结构是从用户角度来看数据库,对使用Oracle的用户来说,一般只关心数据库的逻辑结构,如关心表、视图等。逻辑结构从操作系统中是看不到的,只能通过数据字典查询到。
2.6.1 逻辑结构概述
从逻辑结构上讲,Oracle包括表空间(Tablespaces)、段(Segments)、区(Extents)、数据块(Data Blocks)以及模式(Schema)。数据库由若干个表空间组成,表空间又由若干个段组成,段由区组成,区是磁盘空间分配的最小单位。区又由数据块组成,数据块既是逻辑单位,又是物理单位,数据库中I/O的读取是以数据块为单位的。
数据库的逻辑结构是要通过物理结构来实现的,数据库的逻辑结构和物理结构的关系如图2-13所示。
2.6.2 表空间
表空间(Tablespace)是数据库的逻辑划分,一个Oracle数据库至少有一个表空间,称作System表空间。为了方便管理和提高系统的性能,系统通常还会划分出一些附加表空间给用户和应用程序,如USER表空间,给一般用户使用,UNDO表空间供回滚或撤销使用。
一个表空间对应于磁盘上的一个或多个数据文件,如图2-14所示。
表空间还有如下特点。
一个表空间只能属于一个数据库。
一个表空间在某一时刻只能属于一个数据库。
表空间可以由一个或多个段组成。
当创建一个新的数据库对象,例如表或索引,Oracle会将对象存储在指定的表空间内;如果没有指定,Oracle会储存在缺省的表空间内。
如图2-15所示,表空间内的数据库对象存储在数据文件中,数据库对象和表空间的关系如下。
当表空间中只有一个数据文件时,Oracle在这个表空间的唯一文件中存储全部的数据库对象。
当表空间含有多个数据文件时,Oracle可以将数据库对象存储在这个表空间内任意的数据文件中,甚至一个数据库对象可以存储在多个数据文件中。
2.6.3 System表空间、SYSAUX表空间以及其他表空间
2.6.2节讲解了表空间的基本概念,为了让用户能够更深入了解表空间,本节将详细介绍一些常见的表空间,分别为System表空间和SYSAUX表空间等。
1.System表空间
前面讲到,一个Oracle数据库至少有一个表空间,即System表空间。当创建数据时,必须指明System表空间的数据文件的特性,如数据文件名称、大小。System表空间的作用有两个。
Oracle在系统表空间中存储数据库的数据字典(数据字典将在后面讨论,数据字典内存储了Oracle自身的内部结构信息)。
Oracle在系统表空间中存储全部的PL/SQL程序的原代码和编译后的代码,例如存储过程、函数、包、数据库触发器。如果要大量使用PL/SQL,用户就应该设置足够大的System表空间。
2.SYSAUX表空间
SYSAUX表空间是System表空间的辅助表空间,许多数据库的工具和可选组件将其对象存储在SYSAUX表空间内。它是许多数据库工具和可选组件的默认表空间,如Oracle Enterprise Manager Grid Control工具,在Oracle 10g之前,它的对象存在自己的oem_repository表空间内,Oracle 10g则存在SYSAUX表空间内。
3.其他表空间
一个Oracle数据库系统有多个表空间,创建数据库时,除默认创建System表空间外,Oracle还会创建其他表空间,主要有以下几个。
Users表空间,用于储存用户的数据。
Undo表空间,用于事务的回滚、撤销。
Temp临时表空间,用于存放Oracle运行中需临时存放的数据,如排序的中间结果。
Oracle将数据库划分多个表空间,可以独立地管理各个表空间数据,调节各个表空间的属性以适应不同的需要。
根据表空间的不同属性,表空间分为以下几类。
1.联机表空间和脱机表空间
如果不想使用某表空间,用户可以将这个表空间设置为脱机状态。联机表空间表示表空间可用,用户可以访问其中的信息。脱机表空间表示表空间不可用。将表空间设置脱机状态后,表空间仍在数据库内,但用户不能访问其中的信息。
数据库的System表空间必须是联机状态,因为对数据的正常操作都要访问System表空间的数据字典,否则会提示出错。
2.永久表空间和临时表空间
大多数表空间是永久表空间,永久表空间内存储了需永久保存的数据,数据库实例关闭后,数据仍存在数据库中,如一些表、索引、视图等的数据。
临时表空间的作用是给数据库建立一个临时的工作区域,在这个临时区域内处理需要消耗大量内存的操作,如连接查询、大数据量的排序等。
3.表空间和可读写表空间
表空间创建时默认是可读写表空间,用户可以在这个表空间中存储数据,删除或修改数据。但有些情况下,表空间存储的数据不允许改变,例如表空间内存了历史数据,表空间就不宜更改,这时用户可以将这个表空间设为只读。
2.6.4 段
段是表空间的下一个逻辑单位,段位于表空间当中,由若干个区组成,随着数据的增加,可自动增长。段用来存储数据,每建立起一个表、索引或快照,就要分配一个段。一个段对应一个表空间,不可跨越表空间,但段可以跨越一个表空间中的数据文件。
根据存储的数据类型不同,段可以分为数据段、索引段、临时段和回滚段。段的增大是通过分区个数的增加来实现的,下面我们分别详细介绍各段类型的作用。
1.数据段
数据段是数据库中用于存储数据的段,对于没有用到聚集的基表,一个表对应一个数据段。
2.索引段
索引段用于存储索引数据,一个索引对应一个索引段,如果一张表有两个索引,则要建立两个索引段。有关索引的具体内容,可参考后面的章节。
3.临时段
SQL语句执行过程中常要用一些临时的工作区域,例如为大表排序,排序开始时在用户的临时表空间中自动创建一个临时段,排序结束时又自动清除。
4.回滚段
回滚段是Oracle中比较难管理的一个段,回滚段用于存储数据库修改之前的数据,数据修改失败后,可以从回滚段内取出原来的数据恢复。一个事务只能使用一个回滚段,而一个回滚段中有多个事务的回滚。
Oracle将数据写入回滚段的操作不同于其他段的操作。回滚段是一个区间(Extends)的循环,当一个区间写满时,就写下一个区间,如图2-16所示。如果事务太长,以至于要覆盖自己,Oracle就会分配一个额外的区间,以安全存储这个长事务。
System回滚段是在数据库建立时,建立一个称为System系统回滚段的回滚段,System回滚段位于System表空间中。如果使用System回滚段处理数据库事务压力过大,用户可以建立多个回滚段。处理事务时,用户还可以指定用哪一个回滚段做回滚。
回滚段还分为公有回滚段和私有回滚段。一般的回滚段都是公有的,所有的事务都可用公有回滚段做回滚。但当在并行服务器环境下,用户希望在同一个数据库上,不同的服务器用不同的回滚段,这就产生私有回滚段。
Oracle 10g不推荐使用回滚段。Oracle 10g的回滚功能通过Undo表空间实现,这个表空间由Oracle自动管理,其分配与回收不需要数据库管理员干预。
2.6.5 区
区(Extents)又叫范围,Oracle以区为单位为数据分配储存空间,所以区是Oracle分配磁盘空间的最小单位,一个区由若干个数据块组成。
在数据段中,区的个数受到区的参数限制。在初始创建段时,系统只分配最小的区个数MINEXTENTS。随着段的数据量加大,区也随之增多,但不能超过参数MAXEXTENTS的限制。如果超过了最大区个数,用户就不能再向段中添加数据,否则数据库出错,如图2-17所示。
2.6.6 数据块
数据块是数据库中最小的数据管理单位,Oracle使用数据块存储和提取磁盘上的数据。数据块是在数据库创建时指定的,数据库创建后不能修改。数据块的大小必须等于服务器数据块的大小或它的整数倍。例如,服务器的操作系统块大小为512K,数据块的大小只能是512K、1024K、2048K等。
Oracle 8i以前,数据库使用统一的大小,Oracle 9i和10g内数据库可以同时使用2K、4K、8K、16K、32K大小的数据块。对于系统表空间和默认表空间使用初始化参数DB_BLOCK_SIZE决定大小,其他表空间则可以用初始化参数DB_nK_CACHE_SIZE的大小。
1.数据块的格式
每一数据块的格式是类似的,不管它是包含表、索引还是聚集数据,其格式如图2-18所示。
标题:包含一般的块信息,如块地址、段类型(数据段、索引段、回滚段等)。
表目录:包含存放的表的信息。
行目录:包含块中的行的信息,如数据区中的每一行的首地址。
行数据:包含表或索引数据。
未用空间:可用于插入新行或用于修改行的空闲空间。
2.数据块的可用性和空闲列表
当创建新的数据库对象时,如创建表、索引,Oracle会为对象的相应段分配一个或多个区。因为其中经常会修改或删除,所以系统会留下许多空闲块。这些空闲块被一个空闲列表串接起来,如图2-19所示。
由图2-19可以看到数据块如何删除和加入空闲列表。当向表空间中插入一条新记录时,空闲列表上的所有数据块都可以用来储存新记录,当事务向表中插入越来越多的记录时,数据块空闲比例少于一定阀值(即数据库对象的PCTFREE参数值),Oracle就从空闲列表中将此数据块删除。删除数据时,如果数据块中数据占用的比例大于一定阀值(即数据库对象的PCTUSED参数值),Oracle会重新将这数据块加入到空闲列表中。
3.行链接与数据块的大小
向表中插入新的记录时,Oracle将新纪录放到表的空闲列表的数据块上。最好的情况是该记录能够放入到一个数据块中。这样查询表时,Oracle只需从磁盘读取一个数据块就可以取出全部的这行记录数据。如果某记录存储在两个或多个数据块上,即产生了行链接,读取这行记录时就要读取多个数据块,这就增加了磁盘I/O的压力,所以应尽量避免行链接。图2-20是一个表示行存储的示意图。
当更新一个记录时,Oracle也可能会产生行链接,因为记录更新后,原数据块存储不下更新数据,所以不得不跨数据块存储。
避免行链接的方法之一是合理配置好数据块的大小。如果数据库中有很多超过缺省尺寸的记录,设置较大的数据块会有更好的效果。合理配置PCTFREE、PCTUSED参数的值也能减少行链接。
2.6.7 用户与模式
用户不是数据库中的一个物理结构,但与数据库中的对象有重要的关系,用户拥有数据库对象。例如,Oracle的系统用户SYS拥有Oracle系统字典表,这些字典表存储了数据库的结构信息;用户SYSTEM拥有可访问数据字典的视图,其他用户可访问这些视图。
数据库创建对象的时候必须在用户下进行,可以定义一些用户参数,使指定的表空间作为用户的缺省表空间。
模式是用户拥有的对象的集合。模式是关系型数据库中一个重要的概念,Oracle在模式中组织管理关系型数据库对象。例如,在模式中组织全部的表、视图、索引等。模式是个逻辑概念,和数据库的物理存储没有任何关系。
Oracle中,用户与模式的概念紧密相连,常常被人误以为是一个概念。用户与模式是一一对应的,而且名字一样,但是是不同的概念。用户拥有数据库对象,而模式是数据库对象的集合,可以说某人以某用户登录数据库,而不能说某人以某模式登录库。在其他的关系型数据库中,用户和模式的差别很明显。
2.6.8 表
Oracle系统中将关系模型中的关系称为表。表是Oracle数据库中数据存储的基本单位,其数据按行、列存储。每个表由表名以及列集合组成。每个表最多包含254列。每一列有列名、数据类型、宽度和精度。对于表的每一列可指定完整性约束。
一般,表的持有者(Owner)就是该表的建立者,但DBA用户可为别的用户建立表。这时,DBA为表建立的者,但不是表的持有者。
Oracle中的表的存放和物理文件并不一一对应,这和其他数据库不同。对没用使用聚集(Cluster,后面会介绍)的表,Oracle会为表在指定的表空间中自动分配一个数据段,在这个段中存放表的数据,表数据以行的方式存放。表的行存储有以下几个特点。
从逻辑上讲,每个表的行数没有限制。
数据存储在物理的数据块上,行可以分散在个数据块上,块之间用块链接连起来。
各行之间的存储在物理上没有空隙。
列长为0表示NULL。
空值不存储。
当表有很高的并发性要求时,用户可以将这张表存储在多个区(Extents)中,这些分区可以位于不同的表空间中。Oracle支持按某个字段值的范围进行分区。一个分区就是一个段,用户可以为每个分区配置不同的存储参数。
2.6.9 列与数据类型
创建表时,用户要确定表中各列的属性,从而确定表基本结构。每一个列有一个数据类型,数据类型限制了列可以接受哪些数据。
Oracle支持很多数据类型,不管是数据库管理人员,还是开发人员,都要对Oracle的数据十分了解。表2-2列出一些常见的数据类型。
除了表2-2所列的数据类型以外,Oracle还支持ANSI/ISO(ANSI,American National Standards Institute;ISO,International Organization of Standards)的标准数据类型。如果用ANSI/ISO数据类型建表,Oracle会自动转化为表2-3所示的数据类型。对应的转换如表2-3所示。
2.6.10 ROWID伪列
ROWID标识Oracle中物理上独一无二的一行,它表示的是行的物理地址。Oracle通过ROWID建立表的索引和表之间的连接。
ROWID是Oracle的伪列,在表中实际并不存在该列,更没有该列的数据。但在对表进行操作时,用户可以像一个实际存在的列一样对它读取,如下SQL语句所示。
SQL>SELECT ROWID, ENAME FROM EMP;%ROWID在EMP表中并没定义
ROWID分物理ROWID和逻辑ROWID。物理ROWID内存放的是普通表、聚集表、分区表等的行物理地址。使用物理ROWID能最快地找到行,因为物理ROWID存放的是物理地址。一般行建立后,这个行的ROWID就固定了,除非行的存储位置移动,例如用Export和Import工具重装了数据库。物理的ROWID又分为两种:在Oracle 7和Oracle 7之前叫Restricted ROWID,Oracle 7之后叫Extended Rowids。
1.Restricted ROWID
Restricted ROWID用二进制表示物理地址,用SQL语句查询这个ROWID时,会自动将它转换为16进制的VARCHAR2字串。Restricted ROWID包括三部分,数据块号,行号和数据文件号。
数据块号:行所处的数据块号。
行号:在块中的行号。
数据文件号:所处的数据文件号。在同一个数据库中,数据文件号是唯一的。每一个数据库的第一个数据文件号都是1。
举例说明,ROWID为:00000DD5.0001.0002。DD5就是数据块号;0001就是在块中的行号;0002就是数据文件号。
2.Extended Rowids格式
新的Extended Rowids使用字符A-Z,a-z,0-9,-,+表示行。Extended Rowids使用的是相对值,所以必须存放Segment的标识,否则相互之间会混淆。Oracle 8在ROWID中加入数据库对象的Segment号,用来标识对象是TABLE还PARTITION。
Extended Rowids的格式分四部分:OOOOOOFFFBBBBBBRRR。
OOOOOO:代表数据库对象所处的段号。
FFF:代表表空间中的数据文件号。
BBBBBB:行所在的数据块号。
RRR:在数据块中的行号。
举例,如ROWID为:AAAAaoAATAAABrXAAN,AAAAao就是对象的段号,AAT就是数据文件号,AAABrX是行所在的数据块号,AAN是行在数据块中的行号。
3.逻辑ROWID
对索引组织表(参考2.6.12节),并没有固定的物理地址,它的行存储随着表的插入经常移动,所以不能用物理ROWID来读取该行。为了标识该行,Oracle提供了一个逻辑ROWID的方法,逻辑ROWID是通过表主键建立。Oracle通过逻辑ROWID建立二次索引。
2.6.11 约束条件
约束条件(Constraint)就是强制数据库的表列满足一个特定的规则,当向这个表中插入或修改时,必须服从这些约束条件,否则不进行这些操作。Oracle数据库中.约束条件包括Primary Key、Not Null、Check、Unique和Foreign Key五种类型。
Primary Key约束,即主键约束,可以是表中的一个或多个列,它用于标识每个行的唯一性。数据库中的主键列必须非空(Not Null),并且值不能重复。
Not Null约束,即非空约束。如果数据库的某列规定Not Null,那么在向该列插入数据时,该列必须有数据。
Check约束即检查约束,确保列的值要符合一定条件,如月份必须大于1小于12。
Unique约束,即唯一性约束,表示该列数据值不能相同。
Foreign Key,即外键,表示该列值是引用其他表的列。定义外键的列叫从表,而被引用列的表叫主表。
2.6.12 索引
索引和表一样,是数据库中十分常见的概念,索引为提高数据检索性能而建立,利用它可快速地确定所要检索信息的物理存储路径。
在数据库中,性能的一个主要衡量标准是就是数据库的存取速度,而磁盘I/O又是决定存取速度的重要因素,访问I/O越少性能越好。使用索引能减少使用I/O的次数。索引类似于书的目录,在书目录中找内容,会比到书正文中一页一页找内容要快得多。
索引在逻辑上和物理上都独立于表数据,它在表外存了被索引列的全部数据和数据在表中的行地址。它的建立或删除对表没有影响,所有应用可继续处理。索引数据的检索性能几乎保持常数。索引和表的关系如图2-21所示。
索引可在表的一列或多列上建立,一旦建立后,Oracle自动维护和使用,索引对用户是完全透明的。索引有唯一索引和非唯一索引,一个索引的索引列最多为16列。Oracle提供几种不同类型的索引实现方式,B树索引、位图索引、反向键索引以及函数索引。
1.B树索引
B树索引是最常用的索引,它的存储结构类似书的索引结构,有分支节点和叶节点,分支节点相当于书的大目录,叶节点相当于具体到书页的索引。
B树索引是Oracle缺省使用的索引。分支节点包括两部分:用于分支判断的一个值和指向下一层节点的指针(即下一个节点的物理位置)。叶节点也包含两个部分:该记录的索引列值和该记录的ROWID(即行的物理存储位置)。叶节点的块是双向链接的,这样可以以索引值快速地进行升序和降序扫描。一棵典型的B树如图2-22所示。
图2-22假设索引列是整数,如要查找索引值为11的行,先从根节点10,再找到15,最后取到值为11数据块,从中取出行地址,中间不需要全表扫描。为了简化,图中的分支节点只存了一个关键字。实际情况中,用户可根据数据块的大小存多个关键字,假如存了n个关键字数,一个节点需存n+1个指针。
2.位图索引
位图索引也是按B树索引组织的,但它在叶子中存的是位图,而不是ROWID列表。位图索引用位来表示索引健值,当行中包含这个索引键值,就将该位置1,然后用一个映射函数将该位转化为ROWID。位图索引(Bitmap Indexes)只有Oracle企业版中才提供。
下面我们举个例子,如图2-23所示,给Parts表加了两个索引:颜色和尺寸,颜色有三种:红、绿、蓝。尺寸有三种:大、中、小。
进行查询时,如上图2-23所示的Select语句,根据where语句内容生成一个二进制列,将对应条件值中“红“和“中”的位置1,其他位置0,分别和索引位图相“与”,结果为“真”的就是所要的结果,如图2-23所示,取出了“002”,“005”行。位图索引的优点有几个。
用一个位来表示一个索引健值,节省了存储空间。
对and,or或=的查询条件,位图索引有很高的效率,计算机善于处理0,1的数据。
位图索引适合决策支持系统与数据仓库的数据查询。
以下几种情况不适合使用位图索引。
经常插入或更新的表,不适合使用位图索引。
索引列的值很多,值可选范围大,这种情况下建立索引的代价很高。
3.逆键索引
逆键索引(reverse key indexes)就是将除ROWID列之外的每一个索引列的字节颠倒,但保持列的顺序。逆键索引的目的就是解决实时应用簇(Real Application Clusters,参考后面章节)对索引的读写总是集中在一小块地方的问题(对同一数据块的频繁读写,容易引起磁盘坏道,而且易导致I/O瓶颈)。将索引列值颠倒后,系统能将对索引的读写分散到索引的整个区域。使用逆键索引能提高OLTP实时应用簇的性能,但缺点是不能用逆健索引进行范围检索。
4.函数索引
函数索引(Function-Based Indexes)和B树索引类似,只不过在索引内存储的是一个函数的计算结果。举例说明,创建一个函数索引,这个函数使用Oracle内部函数UPPER,将name都改成大写存储。
SQL>CREATE INDEX uppercase_idx ON employees (UPPER(name));
SQL>SELECT * FROM employees WHERE UPPER(fname) = ’RICHARD’;
因为索引内存储的是name的大写,所以查询的速度会比没用函数索引快。使用函数索引前用户要将初始化参数QUERYREWRITE_ENABLED设为TRUE,将QUERY_REWRITE INTEGRITY设为TRUSTED,同时将COMPATIBLE参数设成8.0.1以上。
5.索引组织表
索引组织表(Organization Index)将表和数据存储在一起,索引组织表缩写为IOT。索引组织表适合主要通过主键访问数据的表。
一张索引组织表就是一棵B树,只是叶子节点上存储的不是ROWID,而是整行的数据,如图2-24所示。因为表行和索引存在一起,所以每一行没有物理的ROWID,索引组织表使用逻辑的ROWID,对索引组织表的访问和其他表的访问方法一样。
用户还可以在索引组织表上建立二次索引。建立二次索引时,Oracle使用逻辑ROWID。普通表和索引组织表的区别如表2-4所示。
2.6.13 视图
在关系模型中我们将视图称为虚表,它是由一个或多个表(或视图)中的数据提取组成,用查询来定义,所以视图也叫存储的查询(Stored Query)。视图在许多地方可以当作一般表使用。
但视图与表不同,一个视图不分配任何存储空间,视图不真正地包含数据,而由查询获得数据。因为视图是由表导出的,所以视图与表存在着许多类似。和表一样,视图最多可定义254列。视图只能用来查询,而不能对它进行修改、插入或删除。视图有以下四个优点。
视图可以限制对表的存取,因此视图为表提供附加的只读安全性。
视图可以隐藏数据的复杂性,例如一个视图可用连接操作定义,从多个表中抽取所需的行和列。视图可隐藏信息来源。
视图可以简化操作命令。
视图可以实现表的存储场地透明性。用户只需关心视图的结构,而不必关心数据如何存储。
但使用视图会降低数据库的存取速度,因为用视图提取数据时,数据库要先解析视图,再从基表中取数据。
2.6.14 序列
序列提供唯一的一个数值来简化程序设计工作。序列(Sequence)定义存储在数据字典中。当一个序列第一次被查询调用时,它将返回一个预定值。在随后的每一次查询中,序列将产生一个按其指定的增量增长的值。序列可以是循环的,或者是连续增加的,直到指定的最大值为止。
序列不可回退,每当数据库看到取下一个序列值的命令,序列值就加一个指定值。即使事务执行失败,数据库也不会退回原来的值。
2.6.15 过程与过程包
过程(Procedure )是一个PL/SQL语句块,它存储在数据字典中并且可被应用程序调用。用户可以使用过程存储数据库中频繁使用的应用逻辑。当执行一个过程时,这个过程中的语句将作为一个整体执行。过程不返回任何值。
系统用户可以使用存储的过程来帮助实施数据的安全性。系统用户可以撤销用户直接访问应用程序中的一些表的权限,而是授权用户执行访问这些表的一个过程。当执行过程时,它将以过程拥有者的权限来执行对表的访问。除此之外,用户就不能访问这些表。
系统用户可以使用过程包(Package)将过程及函数安排在一个包中,这样便于用户使用和系统管理。包说明和包体都存储在数据字典中。过程包在过程及函数所需要的管理任务中非常有用。
过程包中的不同元素可以定义为“公用”或“私有”。过程包的用户可以使用公用元素,私有元素则对用户是隐藏的,它只能被其他过程调用。
函数、过程包和过程的源代码都存储在数据字典表中。如果应用程序经常使用软件包,就必须增加System表空间的容量以适应数据字典容量的增长。例如Oracle财务软件(Finacial)工具中就可能需要一个大于250MB的System表空间。过程包的数量及复杂性在使用中直接影响着SGA的SQL共享池(Shared SQL Pool)部分的大小。
2.6.16 函数
函数(Function)是存储在数据库中的代码块,和其他语言的函数类似,Oracle函数可以把值返回给调用它的程序。
用户可以建立自己的函数,并在SQL语句中调用它们,就像执行Oracle内部函数一样。
例如,Oracle提供SUBSTR内部函数来截取字串,用户可以自己定义一个新函数,如称作MY_SUBSTR,在MY_SUBSTR函数中用户不但可以保留原来SUBSTR的功能,而且可以加去掉两头空格的功能。这个新函数的使用和Oracle内部函数一样。对使用PL/SQL进行程序开发的程序员来说,写函数是司空见惯的事情。
2.6.17 触发器
触发器(Trigger)也是存储在数据库中的过程,一个特定的数据库事件发生时就执行这个过程。触发器可以用来检查数据库的完整性,实施附加的安全等。
Oracle中允许对表发出的INSERT、UPDATE或DELETE语句隐式地执行定义的过程,这些过程称为数据库触发器。触发器与相关表分别存储。触发器只可以定义在表上。在许多情况下,触发器用于很高级的专用数据库管理系统,来补充ORACLE的标准功能。触发器一般用于以下各种情况。
自动地生成导出的列值
防止无效的事务
实施更复杂的安全性检查
在分布式数据库中实施跨越结点的引用完整性
实施复杂的事务规则
提供透明事件日志
提供高级的审计
维护表复制同步
收集与表存取有关的统计
触发器和约束条件都可以用于约束数据的输入,但它们之间有区别。约束条件强制要求表的所有数据都必须满足这个约束条件。而触发器只约束在触发器定义之后的数据,所以不能保证表中全部数据符合该触发器的规则。触发器实施瞬时约束,即在数据改变时实施约束。
触发器由三部分组成:触发事件或语句、触发器的限制、触发器动作。触发事件或语句指激发触发器的SQL语句,如对指定表INSERT、UPDATE或DELETE语句。触发器的限制实际上为一个布尔表达式,当触发器激发时该条件必须为TRUE。触发器的限制是用WHEN子句来指定的。触发器的动作为一个PL/SQL过程,由SQL语句和PL/SQL语句组成。当触发语句发出,触发器的限制计算得TRUE时,执行它。
触发器的类型分为行触发器与语句触发器。行触发器指对受触发语句影响的每一行,行触发器激发一次。语句触发器指语句执行一次,触发器被激发一次,而与涉及的行数无关。
触发器可以指定触发时间,指定动作的执行是在语句执行之前还是在之后。BEFORE触发器指在语句执行之前执行触发器动作;AFTER触发器指在语句执行之后执行触发器动作。
2.6.18 同义词
同义词(Synonym)是表、视图、快照、序列、过程、函数或包的别名。同义词的定义存储在数据字典中。一共有两种同义词,公用(Public)和专用(Private)。公用同义词可以供数据库中每一个用户存取。专用同义词只供定义者或授权的用户使用。同义词可用于以下两种情况。
同义词可屏蔽对象的名字及其持有者。
同义词可为分布式数据库的远程对象提供位置透明性。
2.6.19 权限及角色
权限就是用户能否进行某种操作,为了保护数据库的安全必须为数据库设置多个权限。如某张表,一些用户可以对它修改,而另一些用户只能浏览。
角色是权限的组合。数据库中有许多的权限,如果对每个权限分别管理,是个很大的工作量。如果将这些权限分组,用户需要某种权限直接就将一组权限授予他,比逐个授予要方便得多,这就是角色。Oracle提供了一系列对权限进行操作的SQL命令。角色有以下特点。
角色不是一种数据库对象,不属于任何数据库用户。
角色的定义存储在数据库的数据字典中。
角色中可以包含许多系统特权与对象特权。
角色授权给用户时,该用户就获得该角色定义的所有权限。
角色权限可以授予用户,也可以授予另一个角色。
用户可以打开和关闭权限的使用。
2.6.20 快照
快照(Snapshot)就是把远程数据库的数据复制到本地数据库,它用于分布式数据库和对实时性要求不强的数据库系统中。本地数据库通过数据库链接选择远程数据库上的数据,然后在本地保存一个副本,可以设置数据库定时自动刷新。用户可以查询快照。使用快照有以下优点。
从本地读取快照表比从远程服务器上读取表要快得多。
建立了远程数据库的快照后,如果远程数据库不可用,还可以继续使用本地的快照。
快照可以设置成只读方式或可更新方式。如果要加速数据读取,还可以对快照使用索引。
2.6.21 聚集
聚集(Cluster)就是把经常访问的表在物理上存储在一起,是存储表数据的一种可选择的方法。它将具有同一公共列值的行存储在一起,这些公共列构成聚集码(Cluster Key)。聚集码在建立聚集时定义。建立聚集时,系统为它建立一个数据段,在建立聚集后必须为它的聚集码建立索引,之后才能执行SQL语句。聚集存在与否,对用户或应用是透明的,因为对存储在聚集中的表数据的存取方法与非聚集的表数据的存取完全一样。组成聚集码的列不能超过16列,其值的长度不能超过数据块可用空间的三分之一。
聚集是一个不容易理解的概念,为便于理解,我们详细介绍聚集的存储原理。假设有两张表EMP和DEPT,表的内容分别如表2-5、表2-6所示。
在不使用聚集的情况下,这两张表的数据分别存储在各自的段中。假如要取出部门号为D1的员工名称和员工所在部门的名称,系统要先从EMP表中取出D1对应的所有员工名称和其所在的部门号,这里是Joan和D1,然后根据部门号取出部门名称Market,这期间至少要访问I/O两次。
而如果用聚集,如图2-25所示,系统先通过聚集码索引找到部门D1的数据块1,然后将数据块1中的数据全读取出来。这样只需访问一次I/O,大大提高了数据存取的效率。
因为聚集将不同表的相关行存储在一起,所以可改进聚集表的存取时间,减少磁盘的I/O次数。并且数据块内只存储了一个聚集码值,有效地节省了存储空间。但聚集可能会降低一些操作的执行速度。如对同一张表,不使用聚集时执行插入、修改、删除操作比使用聚集快得多,因为对聚集的这些操作容易引起聚集表的物理重组。因此聚集适用于更新较少的表。而且如果对聚集进行全表扫描,还可能会引起更多的I/O操作。
2.6.22 散列聚集
2.6.21节的聚集使用索引寻找数据块,而散列聚集(Hash Cluster)和索引聚集不同。散列聚集根据Hash函数计算聚集码产生的结果,在聚集中物理地存储记录。产生相同结果的所有记录将存储在相同的数据块或散列桶(Hash Bucket,桶中的Hash值都一样)中。当要查找表中的记录时,系统用Hash函数计算后根据计算的结果到不同的桶中取记录。服务器可能只用一次磁盘I/O就可以取出全部记录数据。
散列聚集的缺点是对查找一定范围的记录效率低,而且对于频繁地数据插入与更新操作,散列聚集的效率不高。
2.6.23 数据库链
数据库链是一个本地(Local)数据库到远程(Promote)数据库的路径。Oracle通过建立数据库链访问远程数据库。数据库链用两种,一种是公用数据库链,本地数据库中的所有用户都可以使用;一种是私有的,专门为某个用户创建。
创建一个数据库链接时,必须指定与数据库相链接的用户名、用户的口令以及与远程数据库相链接的服务器名字。如果不指定用户名,Oracle将使用本地用户名和口令来建立与远程数据库的链接。下面是创建一个公用链接的例子,这个例子打开由网络服务(service)“DB1”指定的数据库。当链接上这个数据库后,我们用用户“HR”、口令“HR1”登录。服务名在本地网络配置文件tnsnames.ora定义。
Create public database link my_link %数据库链接名称my_link
connect to HR identified by HR1
using 'DB1'
除了在表名后面加限定范围“@ my_link”后缀外,对远程表的操作与对本地表的操作一样。