数据库原理
第1章 数据库系统结构
从数据库管理系统的角度看,数据库系统通常采用三级模式结构,这是数据库系统内部的体系结构。
1. 数据库系统模式的概念
模式(Schema)是数据库中全体数据的逻辑结构和特征的描述。它仅仅涉及型的描述,不涉及具体的值。某数据模式下的一组具体的数据值称为模式的一个实例(Instance)。同一个模式可以有很多实例。因此,模式是相对稳定的,反映的是数据的结构及其联系,而实例是不断变化的,反映的是数据库某一时刻的状态。
2. 数据库系统的三级模式结构
通常DBMS把数据库从逻辑上分为三级,即外模式、模式和内模式,它们分别反映了看待数据库的三个角度。
为了支持三级模式,DBMS必须提供在这三级模式之间的两级映像,即外模式/模式映像与模式/内模式映像。
2.1 模式
模式也称概念模式或逻辑模式,是数据库中全体数据的逻辑结构和特征的描述,是所有用户的概念视图。视图可理解为一组记录的值,用户或程序员看到和使用的数据库的内容。
模式处于三级结构的中间层,它是整个数据库实际存储的抽象表示,也是对现实世界的一个抽象,是现实世界某应用环境(企业或单位)的所有信息内容集合的表示,也是所有个别用户视图综合起来的结果,所以又称为用户公共数据视图。
一个数据库只有一个模式。数据库模式以某一种数据模型为基础,综合考虑了所有用户的需求,并将这些需求有机地结合成一个逻辑整体。定义模式时不仅要定义数据的逻辑结构(如数据记录由哪些项组成,数据项的名字、类型、取值范围等),而且要定义与数据有关的安全性、完整性要求,定义数据之间的联系。
2.2 外模式
外模式又称子模式或用户模式或用户视图,是三级结构的最外层,也是最靠近用户的一层,反映数据库用户看待数据库的方式,是模式的某一部分的抽象表示。它是数据库用户看见和使用的局部数据的逻辑结构和特征的描述,是数据库用户的数据视图,是与某一应用有关的数据的逻辑表示。它由多种外记录值构成,这些记录值是概念视图的某一部分的抽象表示。即个别用户看到和使用的数据库内容。
外模式通常是模式的子集。一个数据库可以有多个外模式。由于它是各个用户的数据视图,如果不同的用户在应用需求、看待数据的方式、对数据保密的要求等方面存在差异,则其外模式描述就是不同的。每个用户只能调用他的外模式所涉及的数据,其余的数据他是无法访问的。
2.3 内模式
内模式又称为存储模式或物理模式,是三级结构中的最内层,也是靠近物存储的一层,即与实际存储数据方式有关的一层,由多个存储记录组成,但并非物理层,不必关心具体的存储位置。一个数据库只有一个内模式。它是数据物理结构和存储方式的描述,是数据在数据库内部的表示方式。如记录的存储方式是顺序存储还是散列(Hash)方法存储;数据是否压缩存储,是否加密等。
在数据库系统中,外模式可有多个,而概念模式、内模式只能各有一个。内模式是整个数据库实际存储的表示,而概念模式是整个数据库实际存储的抽象表示,外模式是概念模式的某一部分的抽象表示。
3. 数据库系统的二级映像
为了能够在内部实现这三个抽象层次的联系和转换,DBMS 在三级模式之间提供了二级映像(外模式/模式映像和模式/内模式映像)功能。这两层映像,使数据库系统中的数据具有较高的逻辑独立性和物理独立性。
3.1 外模式/模式映像
外模式描述的是数据的局部逻辑结构,而模式描述的是数据的全局逻辑结构。数据库中的同一模式可以有任意多个外模式,对于每一个外模式,都存在一个外模式/模式映像。
它确定了数据的局部逻辑结构与全局逻辑结构之间的对应关系。例如,在原有的记录类型之间增加新的联系,或在某些记录类型中增加新的数据项时,使数据的总体逻辑结构改变,外模式/模式映像也发生相应的变化。
这一映像功能保证了数据的局部逻辑结构不变,由于应用程序是依据数据的局部逻辑结构编写的,所以应用程序无需修改,从而保证了数据与程序间的逻辑独立性。
3.2 模式/内模式映像
数据库中的模式和内模式都只有一个,所以模式/内模式映像是唯一的。它确定了数据的全局逻辑结构与存储结构之间的对应关系。例如,存储结构变化时,模式/内模式映像也应有相应的变化,使其概念模式仍保持不变,即把存储结构的变化的影响限制在概念模式之下,这使数据的存储结构和存储方法较高地独立于应用程序,通过映像功能保证数据存储结构的变化不影响数据的全局逻辑结构的改变,从而不必修改应用程序,即确保了数据的物理独立性。
综上所述,数据库系统的三级模式和二级映像使得数据库系统具有较高的数据独立性。将外模式和模式分开,保证了数据的逻辑独立性;将模式和内模式分开,保证了数据的物理独立性。在不同的外模式下可有多个用户共享系统中数据,减少了数据冗余。按照外模式编写应用程序或输入命令,而不需了解数据库内部的存储结构,方便用户使用系统,简化了用户接口。
第2章 查询优化原则
查询优化主要是通过合理安排操作的顺序,来提高系统效率。优化是相对的,变换后的表达式不一定是所有等价表达式中执行时间最少的。因此,优化没有特定的模式,常根据经验,运用下列策略来完成。
(1)尽可能早地执行选择操作。在查询优化中,这是最基本的一条。选择运算可以水平分割关系,能使中间结果显著变小,从而使执行时间成数量级的减少。
(2)在一些使用频率较高的属性上,建立索引和分类排序,这样在执行这些属性域上的条件查询时,DBMS就可以利用索引表和分类排序表进行折半查找和二叉排序树查找,这可大大提高查询效率。
(3)同一关系上的投影和选择运算同时进行,这样可避免重复扫描关系,从而节省操作时间。
(4)把某些选择运算同其之前执行的笛卡儿积结合起来成为一个连接操作。笛卡儿积结果较大,选择后元组减少;两个操作一次完成,需对连接后的元组进行检查,决定取舍,将减少空间和时间的开销。
(5)把投影运算与其前后的双目运算结合起来进行,没有必要为去掉某些属性而扫描一遍关系。
(6)找出公共子表达式,并将该表达式结果预先计算并加以保留,需要时直接从文件读取,以免重复计算。
第3章 关系数据库规范化
为使数据库设计合理可靠、简单实用,形成了关系数据库的规范化理论。它是根据现实世界存在的数据依赖而进行的关系模式的规范化处理,从而得到一个合理的数据库设计效果。规范化理论包括3个内容。① 数据依赖,这是核心,主要研究数据之间的联系;② 范式,是关系模式的标准;③ 模式设计方法,是自动化设计的基础。
数据依赖(Data Dependency)是同一关系中属性间的相互依赖和相互制约。数据依赖包括函数依赖(Functional Dependency)、多值依赖(Multivalued Dependency)和连接依赖(Join Dependency)。
1. 函数依赖
数据依赖包括函数依赖、多值依赖和连接依赖。函数依赖是数据依赖的一种,它反映了同一关系中属性间一一对应的约束。函数依赖是关系规范化的理论基础。
定义:
设R(U)是一个属性集U 上的关系模式,X 和Y 是U 的子集。
若对于R(U)的任意一个可能的关系r,如果r中不存在两个元组,它们在X上的属性值相等,
而在Y上的属性值不等,则称“X函数确定Y”或“Y函数依赖于X”,记作X→Y。
另外一种更加直观的定义如下。
设R=R(A1,A2,…,An)是一个关系模式(A1,A2,…,An是R的属性),X⊆{A1,A2,…,An},Y⊆{A1,A2,…,An},即X和Y是R的属性子集,
T1、T2是R的两个任意元组,即T1=T1(A1,A2,…,An),T2=T2(A1,A2,…,An),
如果当T1(X)=T2(X)成立时,总有T1(Y)=T2(Y),则称“X函数确定Y”或“Y函数依赖于X”,记作X→Y。
1.1 函数依赖的三种形式
当X→Y成立时,则称X为决定因素,称Y为依赖因素。当Y函数不依赖于X时,记为X\→Y。
如果X→Y,且Y→X,则记为X↔Y。
函数依赖可以分为如下三种基本情形。
1.平凡函数依赖与非平凡函数依赖
定义: 在关系模式R(U)中,对于U的子集X和Y,如果X→Y,但Y不是X的子集,则称X→Y是非平凡函数依赖。若Y是X的子集,则称X→Y是平凡函数依赖。
2.完全函数依赖与部分函数依赖
定义: 在关系模式R(U)中,如果X→Y,并且对于X的任何一个真子集X′,都有XY,则称Y完全函数依赖于X,记作XY。若X→Y,但Y不完全函数依赖于X,则称Y部分函数依赖于X,记作XY。
如果Y对X部分函数依赖,X中的“部分”就可以确定对Y的关联,从数据依赖的观点来看, X中存在“冗余”属性。
3.传递函数依赖
定义: 在关系模式R(U)中,如果X→Y,Y→Z,且,则称Z传递函数依赖于X,记作XZ。
2.关系模式的分解
设有关系模式R(U, F),给定U 设有关系模式R(U, F),给定U 的一个子集的集合{U1,U2, …,Un},对每个i,j(1≤i, j≤n),有 Ui⊄Uj,U=U1∪U2∪…∪Un,Fi(i=1,2,…,n)是 F 在 Ui上的投影。如果用一个关系模式的集合 ρ={R1(U1,F1),R2(U2,F2),…,Rn(Un,Fn)}代替 R(U,F),就称 ρ是关系模式R(U,F)的一个分解。
在R(U,F)分解为ρ的过程中,需要考虑以下两个问题。
(1)分解前的模式R和分解后的ρ是否表示同样的数据,即R和ρ是否等价的问题。
(2)一个关系模式经分解后,其函数依赖集F也随之被分解,则分解前的模式R和分解后的ρ是否保持相同的函数依赖,即在模式R上有函数依赖集F,在其上的每一个模式Ri上有一个函数依赖集Fi,则{F1,F2,…,Fn}是否与F等价。
如果这两个问题不解决,分解前后的模式不一致,就会失去模式分解的意义。
2.1 无损分解
1.无损分解的定义
设关系模式R(U, F)上的一个分解为ρ={R1(U1,F1),R2(U2,F2),…,Rn(Un,Fn)},F是R(U, F)上的一个函数依赖集。如果对R中满足F的任一关系r,都有
则称这个分解ρ相对于F是连接不失真分解或称无损连接分解,否则就称为有损分解。
2.2 保持函数依赖
设F是属性集U上的函数依赖集,Z是U的一个子集,F在Z上的一个投影用∏Z(F)表示,定义为∏Z(F)={X→Y|(X→Y)∈F+,并且XY⊆Z}。
设关系模式 R(U,F)的一个分解为 ρ={{R1,F1}, {R2,F2},…, {Rn,Fn}},F 是 R 上的依赖集,如果对于所有的i=1,2,…,n,∏z(F)中的全部函数依赖的并集逻辑地蕴涵F中的全部依赖,即
,则称分解ρ保持函数依赖集F,简称ρ保持函数依赖。
3. 关系模式的规范化
关系数据库中的关系必须满足一定的规范化要求,对于不同的规范化程度可用范式来衡量。范式是符合某一种级别的关系模式的集合,是衡量关系模式规范化程度的标准,达到的关系才是规范化的。
目前主要有 6 种范式:第一范式、第二范式、第三范式、BC 范式、第四范式和第五范式。满足最低要求的称为第一范式,简称1NF。在第一范式基础上进一步满足一些要求的为第二范式,简称为2NF。其余以此类推。各种范式之间的关系如下。
1NF⊃2NF⊃3NF⊃BCNF⊃4NF⊃5NF
关系模式的规范化主要解决的问题是关系中数据冗余及由此产生的操作异常。而从函数依赖的观点来看,即是消除关系模式中产生数据冗余的函数依赖。
通常把某一关系模式R为第n范式简记为R∈nNF。
3.1 第一范式
定义: 如果关系模式R中每个属性值都是一个不可分解的数据项,则称该关系模式满足第一范式,简称1NF,记为R∈1NF。
3.2 第二范式
定义: 如果一个关系模式 R∈1NF,且它的所有非主属性都完全函数依赖于 R 的任一候选码,则称R符合第二范式,记为R∈2NF。
3.3 第三范式
定义: 如果一个关系模式 R∈2NF,且所有非主属性都不传递函数依赖于任何候选码,则称R符合第三范式,记为R∈3NF。
3.4 BCNF范式
定义:关系模式R∈1NF,对任何非平凡的函数依赖X→Y(YX),X均包含码,则称R符合BCNF范式,记为R∈BCNF。
由BCNF的定义可以看到,每个BCNF的关系模式都具有如下3个性质。
(1)所有非主属性都完全函数依赖于每个候选码。
(2)所有主属性都完全函数依赖于每个不包含它的候选码。
(3)没有任何属性完全函数依赖于非码的任何一组属性。
BCNF是从1NF直接定义而成的,可以证明,如果R∈BCNF,则R∈3NF。
如果关系模式R∈BCNF,由定义可知,R中不存在任何属性传递函数依赖于或部分函数依赖于任何候选码,所以必定有R∈3NF。但是,如果R∈3NF,R未必属于BCNF。
3.5 多值依赖与第四范式
多值依赖定义:
设有关系模式R(U),X、Y是属性集U中的两个子集,而r是R(U)中任意给定的一个关系。如果有下述条件成立,则称Y多值依赖于X,记为X→→Y:
(1)对于关系r在X上的一个确定的值(元组),都有r在Y中一组值与之对应。
(2)Y的这组对应值与r在Z=U-X-Y中的属性值无关。
此时,如果X→→Y,但Z=U-X-Y≠∅,则称为非平凡多值依赖,否则称为平凡多值依赖。平凡多值依赖的一个常见情形是U=X∪Y,此时Z=∅,多值依赖定义中关于X→→Y的要求总是满足的。
第四范式定义:
关系模式R∈1NF,对于R(U)中的任意两个属性子集X 和Y,如果非平凡的多值依赖X→→Y(),X都含有候选码,则称R符合第四范式,记为R(U)∈4NF。
关系模式R(U)上的函数依赖X→Y可以看作多值依赖X→→Y,如果R(U)属于第四范式,此时X就是超键,所以X→Y满足BCNF。
4. 关系模式规范化步骤
规范化的基本思想是逐步消除数据依赖中不合适的部分,使模式中的各关系模式达到某种程度的“分离”。即采用“一事一地”的模式设计原则,让一个关系描述一个概念、一个实体或实体间的一种联系。若多于一个概念就把它“分离”出去。因此所谓规范化实质上是概念的单一化。
(1)对 1NF 关系进行投影,消除原关系中非主属性对码的部分函数依赖,将 1NF 关系转换成为若干个2NF关系。
(2)对2NF关系进行投影,消除原关系中非主属性对码的传递函数依赖,从而产生一组3NF。
(3)对3NF关系进行投影,消除原关系中主属性对码的部分函数依赖和传递函数依赖(也就是说,使决定属性都成为投影的候选码),得到一组BCNF关系。
以上三步也可以合并为一步:对原关系进行投影,消除决定属性不是候选码的任何函数依赖。
(4)对BCNF关系进行投影,消除原关系中非平凡且非函数依赖的多值依赖,从而产生一组4NF关系。
规范化程度过低的关系可能会存在插入异常、删除异常、更新异常、数据冗余等问题,需要对其进行规范化,转换成高级范式。但这并不意味着规范化程度越高的关系模式就越好。在设计数据库模式结构时,必须以现实世界的实际情况和用户应用需求作进一步分析,确定一个合适的、能够反映现实世界的模式。即上面的规范化步骤可以在其中任何一步终止。
第4章 Oracle 11g的体系结构
4.1 Oracle 11g体系结构概述
完整的Oracle数据库系统通常由两部分组成:实例(INSTANCE)和数据库(DATABASE)。数据库是一系列物理文件的集合(数据文件、控制文件、日志文件、参数文件等),主要功能是保存数据,可以看作是存储数据的容器;实例则是一组Oracle后台进程/线程以及在服务器分配的共享缓冲区。
实例和数据库有时可以互换使用,不过两者的概念完全不同。实例和数据库之间的关系是数据库可以由多个实例装载和打开,而实例可以在任何时间装载和打开一个数据库。但是,一个实例在其生存期最多只能装载和打开一个数据库。
在启动Oracle数据库服务器时,实际上是在服务器的内存中创建一个Oracle实例,然后由这个实例来访问和控制磁盘中的相关文件。Oracle有一个很大的内存块,称为系统全局区(SGA)。当用户连接到数据库时,实际上是连接到实例中,由实例负责与数据库通信,然后再将处理结果返回给用户。
Oracle体系结构由存储(逻辑、物理)结构、内存结构、进程结构组成。其中,内存结构由SGA、PGA组成。进程结构由用户进程和Oracle进程组成,用户进程是根据实际需要而运行的,并在需要结束后立刻结束。Oracle进程又包括服务器进程和后台进程,是指在Oracle数据库启动后,自动启动的几个操作系统进程。
Oracle数据库的存储结构分为逻辑存储结构和物理存储结构,这两种存储结构既相互独立又相互联系。
逻辑存储结构主要描述Oracle数据库的内部存储结构,即从技术概念上描述在Oracle数据库中如何组织、管理数据。从逻辑上来看,数据库是由系统表空间、用户表空间等组成。表空间是最大的逻辑单位,块是最小的逻辑单位。逻辑存储结构中的块最后对应到操作系统中的块。因此,逻辑存储结构是与操作系统平台无关的,能适用于不同的操作系统平台和硬件平台,而不需要考虑物理实现方式,是由Oracle数据库创建和管理的。
物理存储结构主要描述Oracle数据库的外部存储结构,即在操作系统中如何组织、管理数据。因此,物理存储结构是与操作系统平台有关的。从物理上看,数据库由控制文件、数据文件、重做日志文件等操作系统文件组成。
4.2 逻辑存储结构
逻辑存储结构主要描述Oracle数据库的内部存储结构,从技术概念上描述在Oracle数据库中如何组织、管理数据。Oracle的逻辑结构是从逻辑的角度分析数据库的构成,即创建数据库后形成的逻辑概念之间的关系。
在逻辑上,Oracle将保存的数据划分为若干个小单元来进行存储和维护,高一级的存储单元由一个或多个低一级的存储单元组成。Oracle的逻辑存储单元从大到小依次为表空间(Table Space)、段(Segment)、区(Extent)、数据块(Data Block),逻辑存储结构示意如图所示。
由图可知,Oracle的逻辑存储结构是由一个或多个表空间组成,一个表空间由多个段组成,一个段由多个区组成,一个区由多个数据块组成,一个数据块对应一个或多个物理块。
4.2.1 表空间
Oracle的表空间是最大的逻辑单位,在数据库中建立的所有内容都被存储在表空间中,由一个或多个数据文件组成,表空间的大小是它所对应的数据文件大小的总和;数据文件必须正好是一个表空间的一部分。Oracle 11g 的安装会至少创建 2 个表空间:系统(SYSTEM)表空间和系统辅助(SYSAUX)表空间。Oracle 11g的默认安装创建6个表空间,具体如下。
(1)系统(SYSTEM)表空间。存放关于表空间的名称、控制文件、数据文件等管理信息,是最重要的表空间。它属于SYS和System这2个模式(Schema),仅被这2个或其他具有足够权限的用户使用,但是均不可删除或者重命名System表空间。
(2)系统辅助(SYSAUX)表空间。用于减少系统负荷,提高系统的作业效率。
(3)临时(TEMP)表空间。存放临时表和临时数据,用于排序。
(4)用户(USERS)表空间。永久存放用户对象和私有信息,也被称为数据表空间。
(5)撤销(UNDO)表空间。用于在自动撤消管理方式下存储撤消(回退)信息。
(6)示例(EXAMPLE)表空间。用于存放Oracle发布时提供的示例数据库。
4.2.2 段
段是一组数据区,这些数据区形成Oracle视为一个单元的数据库对象,如表或索引,与这些数据库对象是一一对应的,但段是从数据库存储的角度而言的。因此,段通常是数据库最终用户将要处理的最小存储单元。表空间和数据文件是物理存储上的一对多的关系,表空间和段是逻辑存储上的一对多的关系,段不直接与数据文件发生关系。一个段只能属于一个表空间,但一个表空间可以有多个段。Oracle数据库中的段可分为以下4种。
(1)数据段(Data Segment):存储表中的所有数据。
(2)索引段(Index Segment):存储表上最佳查询的所有索引数据。
(3)回滚段(Rollback Segment):存储修改之前的位置和值。
(4)临时段(Temporary Segment):存储表排序操作期间建立的临时表的数据。
数据库中的每个表保存在单个数据段中,一个数据段由一个或多个区组成;对于分区表或集群表,Oracle会为表分配多个段。数据段包括LOB(Large Object,大对象)段,此段存储表段中的LOB定位器列引用的LOB数据(如果未将LOB以内联方式存储在表中)。
每个索引存储在自己的索引段中。与分区表一样,分区索引的每个分区存储在专门的段中,这种类别包括LOB索引段。表的非LOB列、表的LOB列和LOB的相关索引均可以保存在不同的表空间(不同的段)中以提高性能。
4.2.3 区
区是数据库存储空间分配的逻辑单位,是由一系列物理上连续存放的数据块所构成的Oracle存储结构。在一个段中可以存在多个区,区是为数据一次性预留的一个较大的存储空间,直到那个区间被用满,数据库会继续申请一个新的预留存储空间,即新的区,一直到段的最大区间数或没有可用的磁盘空间可以申请。一个区由一个或多个数据库块组成。扩大数据库对象时,为对象添加的空间作为区进行分配。Oracle在数据文件级别管理区。
4.2.4 数据块
数据块是Oracle中的最小存储单元,也是最基本的存储单位,又称逻辑块或Oracle块。在操作系统中,执行I/O操作是以操作系统块为单位,而在Oracle中,执行的I/O操作以Oracle数据块为单位。块的大小是在建立数据库时指定的,虽然在初始化文件中可见,但是不能修改。为了提高磁盘I/O性能效率,块的大小通常是操作系统块大小的整数倍。Oracle的操作都是以块为基本单位的,一个区可以包含多个块,如果区大小不是块大小的整数倍,Oracle实际也扩展到块的整数倍。默认块大小由Oracle初始化参数DB_BLOCK_SIZE指定。
4.3 物理存储结构
物理存储结构主要描述Oracle数据库的外部存储结构,即在操作系统中如何组织、管理数据。Oracle物理存储结构包含3种物理文件:控制文件、数据文件和日志文件,另外还包括一些参数文件。由控制文件来管理数据文件和日志文件,用参数文件来寻找控制文件。数据文件的扩展名为.DBF,日志文件的扩展名为.LOG,控制文件的扩展名为.CTL。
4.3.1 数据文件
一个Oracle数据库可以拥有一个或多个物理的数据文件。一个Oracle数据文件对应于磁盘上的一个物理操作系统文件。Oracle通过表空间创建数据文件,从硬盘中获取存储数据所需的物理存储空间,一个数据文件只能属于唯一的一个表空间。但是,一个表空间可以包含多个数据文件。大文件表空间是例外情况,这个表空间正好包含一个数据文件。
数据文件具有如下特征。
(1)一个数据库可拥有多个数据文件,但一个数据文件只对应一个数据库。
(2)可以对数据文件进行设置,使其在数据库空间用完的情况下进行自动扩展。
(3)一个表空间可以由一个或多个数据文件组成。
数据文件中的数据在需要时可以读取并存储在Oracle的内存储区中。
当数据被修改或是插入新数据时,不必立刻写入数据文件,而是把数据暂时存储在内存,由Oracle的后台进程DBWR来决定何时将其写入数据文件中,这是为了减少磁盘I/O的次数,提高系统的效率。
数据文件是用于存储数据库数据的文件,如表、索引数据等都物理地存储在数据文件中。这就把数据文件和表空间联系在一起。表空间是一个或多个数据文件在逻辑上的统一组织,而数据文件是表空间在物理上的存在形式。没有数据文件的存在,表空间就失去了存在的物理基础;而离开了表空间,Oracle就无法获得数据文件的信息,无法访问到对应的数据文件,这样的数据文件就成了垃圾文件。
数据文件的大小可以有两种方式表示,即字节和数据块。数据块是Oracle数据库中最小的数据组织单位,它的大小由参数DB_BLOCK_SIZE来确定。
4.3.2 控制文件
数据库控制文件是一个很小的二进制文件,它维护着数据库的全局物理结构,用以支持数据库成功地启动和运行。创建数据库时,同时就提供了与之对应的控制文件。在加载数据库时,实例必须首先找到数据库的控制文件。如果控制文件正常,实例才能加载并打开数据库。但是如果控制文件中记录了错误的信息,或者实例无法找到一个可用的控制文件,数据库将无法加载,当然也无法打开。在数据库使用过程中,Oracle不断地更新控制文件,所以只要数据库是打开的,控制文件就必须处于可写状态。
每一个Oracle数据库有一个控制文件,它记录着数据库的物理结构,其中主要包含下列信息类型:数据库名称、数据库数据文件和日志文件的名称和位置、数据库建立日期、日志历史、归档日志信息、表空间信息、数据文件脱机范围、数据文件拷贝信息、备份组和备份块信息、备份数据文件和重做日志信息、当前日志序列数、检查点信息等。
Oracle数据库的控制文件是在数据库创建的同时创建的。默认情况下,在数据库创建期间至少有一个控制文件副本,如在Windows平台下,将创建3个控制文件的副本。
每一次Oracle数据库的实例启动时,它的控制文件都要用于标识数据库和日志文件。当进行数据库操作时,它们必须被打开。当数据库的物理组成更改时,Oracle自动更改该数据库的控制文件。数据恢复时,也要使用控制文件。如果数据库的物理结构发生了变化,用户应该立即备份控制文件。一旦控制文件出现错误,数据库便无法顺利启动。也因为如此,控制文件的管理与维护工作显得格外重要。
4.3.3 日志文件
Oracle的日志文件包括重做日志文件、归档日志文件、警报和跟踪日志文件。
1.重做日志文件
重做日志文件用于记录对数据库的所有修改信息,修改信息包括用户对表、索引或其他Oracle对象进行的添加、修改或删除,以及管理员对数据库结构的修改。重做日志文件是保证数据库安全和数据库备份与恢复的文件。
2.归档日志文件
Oracle数据库可按以下两种模式运行:归档模式(ARCHIVELOG)和非归档模式(NOARCH-IVELOG)。如果数据库处于非归档模式,则循环重用重做日志文件(又称联机重做日志文件)将意味着在出现硬盘故障或其他与介质相关的故障时,重做条目(以前事务的内容)不再可用。以非归档模式运行可以在实例发生故障或系统崩溃时保护数据库的完整性,因为只能在联机重做日志文件中使用已经提交但尚未写入数据文件的所有事务。因此,崩溃恢复的范围仅限于联机重做日志中的当前条目。如果在最早的重做日志文件之前数据文件最近一次备份发生故障,将无法恢复数据库。
与此相反,归档模式将填满的重做日志文件发送到一个或多个指定目标,可以在数据库介质发生故障时,在任何特定的时间点使用备份文件重新构造数据库。例如,如果包含数据文件的硬盘发生崩溃,有了最新的备份数据文件、重做日志文件和归档日志文件,可将数据库的内容恢复到崩溃前的一个时间点。
3.警报和跟踪日志文件
出现故障时,Oracle可以而且经常会将消息写入警报日志文件,对于后台进程或用户会话,则会写入跟踪日志文件。
警报日志文件位于BACKGROUND_DUMP_DEST初始化参数指定的目录中,包含最重要的例行状态消息以及重要错误条件。在启动或关闭数据库时,会将消息以及一系列未采用默认值的初始化参数记录到警报日志中,还会记录 DBA 发送的任何 ALTER DATABASE 或 ALTER SYSTEM命令。此处还会记录涉及表空间及其数据文件的操作,例如,添加表空间、删除表空间以及将数据文件添加到表空间中。
4.4 内存结构
Oracle内存结构主要可以分为SGA(System Global Area,系统全局区)与PGA(Program GlobalArea,程序全局区)。SGA位于系统的共享内存段中,是由所有用户进程共享的一块内存区域。PGA中保存的是某个服务器进程私有的数据和控制信息,它是非共享内存,Oracle为每个用户会话或服务器进程分配一个PGA。
4.4.1 系统全局区
系统全局区SGA被看作是Oracle数据库的一个大缓冲池,这里的数据可以被Oracle的各个进程共享。
SGA是由一组内存结构组成,是一块巨大的共享内存区域,它是所有用户进程共享的一块内存区域。如果多个用户连接到同一个数据库实例,则实例的SGA区中的数据可被多个用户共享。在数据库实例启动时,SGA的内存被自动分配;当数据库实例关闭时,SGA被回收。SGA主要包括以下几个部分:数据缓存区、共享池、重做日志缓冲区、Java池和大池等结构。
1.数据缓存区
该缓存区保存最近从数据文件中读取的数据块,其中的数据被所有用户共享。该缓存又可以细分为以下 3 个部分:Default Pool、Keep Pool、Recycle Pool。如果不是人为设置初始化参数(Init.ora),Oracle将默认为Default Pool。由于操作系统寻址能力的限制,不通过特殊设置,在32位的操作系统上,块缓冲区高速缓存最大可以达到1.7GB,在64位的操作系统上,块缓冲区高速缓存最大可以达到10GB。
2.共享池
共享池(Shared Pool)保存了最近执行的SQL语句、PL/SQL程序和数据字典信息,是对SQL语句和PL/SQL程序进行语法分析、编译、执行的内存区。共享池主要又可以分为库高速缓存区和数据字典高速缓冲区两个部分。
(1)库缓存区(Library Cache)。
解析用户进程提交的SQL语句或PL/SQL程序和保存最近解析过的SQL语句或PL/SQL程序。Oracle DBMS执行各种SQL、PL/SQL之前,要对其进行语法上的解析、对象上的确认、权限上的判断、操作上的优化等一系列操作,并生成执行计划。因为库高速缓存区保存了已经解析的SQL和PL/SQL,所以,应尽量使用预处理查询。
(2)数据字典缓冲区(Data Dictionary Cache)。
在Oracle运行过程中,Oracle会频繁地对数据字典中的表、视图进行访问,以便确定操作的数据对象是否存在、是否具有合适的权限等信息。数据字典缓存了最常用的数据字典信息。数据字典缓存中存放的记录是一条一条的,而其他缓存区中保存的是数据块。
3.重做日志缓冲区
重做日志文件缓冲区(Redo Log Buffer)对数据库的任何修改都按顺序记录在该缓冲区中,然后由日志写入器LGWR进程将它写入重做日志文件。这些修改信息可能是DML语句(如Insert、Update、Delete)或DDL语句(如Create、Alter、Drop)等。
4.Java池
Oracle 8i 以后的版本提供了对Java 的支持,用于存放 Java 代码、Java 程序等,目的是支持在数据库中运行Java程序。Java虚拟机为用户会话中的所有Java代码和数据使用Java池,一般不小于20MB,以便虚拟机运行。如果不用Java程序,没有必要改变该缓冲区的默认大小。
5.大池
大池(Large Pool)是SGA中可选的内存结构。它用于与多个数据库交互的事务、执行并行查询的进程的消息缓冲区,以及RMAN并行备份和还原操作。大池的得名不是因为大,而是因为它用来分配大块的内存,处理比共享池更大的内存。大池用于大内存操作,提供相对独立的内存空间,以便提高性能。DBA可以决定是否需要在SGA中创建大池。需要大池的操作有数据库的备份和恢复、大量排序的SQL语句、并行化的数据库操作。
6.流池
流池(Streams Pool)是Oracle 10g中的一种新池,通过初始化参数STREAMS_ POOL_SIZE来设置其大小。流池保存数据和控制结构,以便支持Oracle Enterprise Edition的Oracle流功能。Oracle流管理分布式环境中数据和事件的共享。如果未初始化STREAMS_ POOL_SIZE初始化参数或将其设置为0,则从共享池分配流操作使用的内存,内存占用量最多可达共享池的10%。
4.4.2 程序全局区
PGA是用户进程连接到数据库并创建一个对应的会话时,由Oracle为服务进程分配的,专门用于当前用户会话的内存区,属于非共享的内存区域。PGA的配置取决于Oracle数据库的连接配置,即共享服务器或专用服务器。
在共享服务器配置中,多个用户进程共享与数据库的连接,共同占用一块内存区,此时,对服务器的内存使用量降低,但用户请求的响应时间延长。如果同时有多个用户连接到数据库,请求频率高且时间短,那么共享服务器环境就是理想环境。
4.4.3 软件代码区
软件代码区存储作为Oracle实例一部分运行的Oracle可执行文件。这些代码区域本质是静态的,只有在安装新软件版本时才会发生变化。Oracle软件代码区通常位于享有特权的内存区,此内存区与其他用户程序分开放置。
Oracle软件代码完全是只读的,可按共享或不共享形式进行安装。如果以共享形式安装Oracle软件代码,当多个Oracle实例在同一软件版本级别和相同服务器上运行时,可以节省内存。
4.5 进程结构
Oracle包括用户进程和Oracle进程两类。Oracle进程又包括服务器进程和后台进程。
(1)用户进程。
当用户运行一个应用程序或启动一个Oracle工具(如SQL *Plus)时,就建立了一个用户进程,其主要作用是在客户端将用户的SQL语句传递给服务器进程。用户进程不是实例的组成部分。
(2)服务器进程。
该进程用于处理用户进程的请求,其处理过程为首先分析SQL命令并生成执行方案,然后从数据缓冲存储区中读取数据,最后将执行结果返回给用户。在Oracle数据库中可以同时存在两种类型的服务器进程,一种类型是专用服务器进程,一个专用服务进程只能为一个用户进程提供服务;另一种是共享服务进程,一个共享服务进程可以为多个用户进程提供服务。
(3)后台进程。
Oracle实例包括两部分,即SGA和一组后台进程。在任意时候,Oracle数据库均可以处理多个并发用户请求,进行复杂的数据操作,同时还要维护数据库系统使其始终具有良好的性能。为了完成这些任务,Oracle具有一组后台进程保证数据库运行所需的实际维护任务。
主要的后台进程有数据库写进程(DBWR)、日志写进程(LGWR)、系统监控进程(SMON)、进程监控进程(PMON)、检查点写进程(CKPT)、归档进程(ARCn)、恢复进程(RECO)和封锁进程(LCKn)。
1.数据库写进程(DBWR)
其主要作用是将修改过的数据缓冲区的数据写入对应数据文件,并且维护系统内的空缓冲区。DBWR是一个很底层的管理缓冲区的后台进程,它批量地把缓冲区的数据写入磁盘,不受前台进程的控制。使用LRU(Least Recently Used,最近最少使用)算法,DBWR首先写入时间最早、活动性最差的块,最常请求的块会在内存中。
1个Oracle实例至少要有1个DBWR进程,初始化参数DB_WRITER_PROCESSES可以设置 DBWR 进程的个数。如果仅使用 1 个 DBWR 进程无法满足系统的需要,可以设置多个DBWR进程,记为DBWn,最多可以启动20个DBWR进程,即DBW0到DBW9和DBWa到DBWj。
以下条件会触发DBWR进程的工作。
(1)系统中没有多的空缓冲区用来存放数据。
(2)CKPT进程触发DBWR等。
2.日志写进程(LGWR)
该进程将重做日志缓冲区的数据写入重做日志文件,LGWR是一个必须和前台用户进程通信的进程。当数据被修改的时候,系统会产生一个重做日志并记录在重做日志缓冲区内。提交的时候,LGWR必须将被修改的数据的重做日志缓冲区内的数据写入日志数据文件,然后再通知前台进程提交成功,并由前台进程通知用户。LGWR承担了维护系统数据完整性的任务。
触发LGWR工作的主要条件如下。
(1)用户提交。
(2)有1/3重做日志缓冲区未被写入磁盘。
(3)有大于1MB的重做日志缓冲区未被写入磁盘。
(4)DBWR 需要写入的数据的 SCN 号大于 LGWR 记录的 SCN 号,DBWR 触发 LGWR写入。
3.系统监控进程(SMON)
该进程的工作主要包含清除临时空间;在系统启动时,完成系统实例恢复;聚结空闲空间;从不可用的文件中恢复事务的活动;OPS 中失败结点的实例恢复;清除 OBJ$表;缩减回滚段;使回滚段脱机。
4.进程监控进程(PMON)
主要用于清除失效的用户进程,释放用户进程所用的资源。如PMON将回滚未提交的工作,释放锁,释放分配给失败进程的SGA资源。
5.检查点进程(CKPT)
检查点进程负责执行检查点,并更新控制文件,启用DBWR进程将“脏”缓存块中的数据写入数据文件(该任务一般由LGWR执行)。CKPT对于许多应用情况都不是必需的,只有当数据库数据文件很多,LGWR在检查点时明显降低性能的情况下才使用CKPT。
CKPT的作用主要就是同步数据文件、日志文件和控制文件。DBWR/LGWR的工作原理造成了数据文件、日志文件、控制文件的不一致,这就需要CKPT进程来同步。CKPT会更新数据文件/控制文件的头信息。当一个checkpoint发生时,Oracle必须更新所有数据文件的文件头,记录这个checkpoint的详细信息。这个动作是由CKPT进程完成的,但是CKPT进程并不将数据块写入磁盘,写入的动作总是由DBWR进程完成的。
以下条件会触发CKPT工作。
(1)在日志切换的时候。
(2)数据库用immediate、transaction、normal选项shutdown数据库的时候。
(3)根据 init.ora文件中 LOG_CHECKPOINT_INTERVAL、LOG_CHECKPOINT_TIMEOUT、FAST_START_IO_TARGET设置的参数值来确定。
(4)用户触发alter system checkpoint。
6.归档进程(ARCn)
归档进程在发生日志切换(Log Switch)时,将重做日志文件复制到指定的存储设备中。只有当数据库运行在ARCHIVELOG模式下,且自动归档功能被开启时,系统才会启动ARCn进程。
1个Oracle实例中最多可以运行10个ARCn进程。若当前的ARCn进程还不能满足工作负载的需要,则LGWR进程将启动新的ARCn进程。Alert Log会记录LGWR启动ARCn进程。
如果预计系统存在繁重的归档任务,例如将进行大批量数据装载,可以通过设置初始化参数LOG_ARCHIVE_MAX_PROCESSES来指定多个归档进程,通过ALTER SYSTEM语句可以动态地修改该参数,增加或减少归档进程的数量。
7.恢复进程(RECO)
恢复进程用于分布式数据库结构,自动解决分布式事务的错误。一个结点的RECO进程会自动地连接到一个有疑问的分布式事务的相关其他数据库。当RECO重新连接到相关的数据库服务时,它会自动解决有疑问的事务。并从相关数据库的活动事务表(Pending Transaction Table)中移除与此事务有关的数据。
8.封锁进程(LCKn)
在并行服务器中用于多个实例间的封锁。
4.6 数据字典
数据字典(Data Dictionary)是Oracle数据库的核心组件,它是由一系列对于用户而言是只读的基础表和视图组成,它保存了关于数据库本身以及其中存储的所有对象的基本信息。数据字典中的表和视图在创建数据库时由Oracle自动创建,并存放在System表空间中,当数据库启动时,System表空间将自动在线(Online)。这些表和视图的拥有者是用户SYS。可以认为数据字典记录了数据库实例自身的重要信息。
数据字典主要有3个用处。
(1)Oracle访问数据字典来查找关于用户、模式对象和存储结构的信息。
(2)Oracle每次执行一个数据定义语句(DDL)时都会修改数据字典。
(3)任何Oracle用户都可以将数据字典作为数据库的只读参考信息。
数据字典由一系列拥有数据库元数据(Meta Data)信息的数据字典基表和用户可以读取的数据字典视图组成。
(1)数据字典基表。数据字典基表属于SYS用户,只有Oracle能够读写这些表,用户不能直接访问这些表;大部分数据字典基表的名称中都包含$这样的特殊符号,这些表中的数据以加密的形式存在。
(2)数据字典视图。数据字典表中的信息经过解密和一些加工处理后,以视图的方式呈现给用户。大多数用户都可以通过数据字典视图查询所需要的与数据库相关的系统信息。用户可以查看以下几种形式的数据字典视图:以USER_开始的视图、以ALL_开始的视图和以DBA_开始的视图。
数据字典的主要内容如下。
(1)系统的空间信息,即分配了多少空间、当前使用了多少空间等。
(2)数据库中所有模式对象的信息,如表、视图、簇、同义词及索引等。
(3)例程运行的性能和统计信息。
(4)所有Oracle用户的信息。
(5)用户访问或使用的审计信息。
(6)用户及角色被授予的权限信息。
(7)列的约束信息的完整性。
(8)列的默认值。
通过数据字典可实现如下功能。
(1)当执行DDL语句修改模式和对象后,Oracle都会将本次修改的信息记录在数据字典中。
(2)用户可以通过数据字典视图获得各种模式对象和对象的相关信息。
(3)Oracle通过查询数据字典表或数据字典视图来获取有关用户、模式、对象的定义信息以及其他存储结构的信息。
(4)DBA可以在数据字典的动态性能视图中监视例程的状态,以将其作为性能调整的依据。
第5章 用户权限与安全
5.1 用户和模式
由于Oracle中的对象是一种基于模式的管理方式,每个数据库对象都显式地属于一个用户,属于这个用户的对象的集合称为模式(Schema),通过灵活地控制用户的权限,即可灵活地控制用户模式对象的安全性。
1.用户(User)
这里所说的用户并不是数据库的操作人员,而是能够连接到数据库的用户账号。要使用户可以访问数据库,必须创建用户账号并为这些账号授予适当的数据库访问权限。
用户是定义在数据库中的一个名称,它是Oracle数据库的基本访问控制机制,用来连接和访问数据库对象。每个Oracle数据库都有一个有效数据库用户列表。当连接和访问某个Oracle数据库时,为了确保数据库的安全性,用户必须使用该数据库中定义的有效用户名和口令,然后才能连接到该数据库实例。
在Oracle中,用户又可以分为2种类型:普通用户和预定义管理用户。
(1)普通用户。
这类用户管理数据对象,拥有对自己创建的对象的所有权限,比如scott用户就是一个普通用户,它不能进行一系列的数据库管理工作。
(2)预定义管理用户。
Oracle数据库在安装时自动创建的用户账户。所有数据库都包括管理账户SYS、SYSTEM、SYSMAN和DBSNMP。
2.模式(Schema)
对Oracle来说,模式是指数据库对象的集合,是对用户所创建的数据对象的总称。
5.2 管理用户
Oracle数据库的安全保护流程可以总结为3个步骤。首先,用户向数据库提供身份识别信息,即提供一个数据库账号;其次,用户需要证明他们所给出的身份识别信息是有效的,这是通过输入口令实现的;最后,假设口令是正确的,那么数据库认为身份识别信息是可信赖的。
5.2.1 数据库的存取控制
数据库的存取控制包括用户认证、用户的表空间设置和配额、用户资源限制和配置文件3个部分。
1.用户认证
为了防止非授权的数据库用户的使用,Oracle提供3种认证方法:操作系统认证、Oracle数据库认证、网络服务认证。
2.用户的表空间设置和配额
关于表空间的使用有几种设置选择:用户的缺省表空间、用户的临时表空间、数据库表空间的空间使用配额。
3.用户资源限制和配置文件
用户可用的各种系统资源总量的限制是用户安全域的部分。利用显式的方式设置资源限制,管理员可防止用户无控制地消耗宝贵的系统资源。资源限制由用户配置文件管理。用户配置文件是指定资源限制的命名集,可赋给Oracle数据库的有效用户。利用用户配置文件可容易地管理资源限制。
5.2.2 权限简介
权限是指执行特定类型SQL语句或访问另一用户的模式对象的权利。权限包括系统权限和对象权限两种类型。
(1)系统权限。执行特定类型SQL语句或者在对象类型上执行一种特定动作的权利,它用于控制用户可以执行的一个或一组数据库操作。
(2)对象权限。访问其他模式对象(表、视图、序列、过程、函数和包)的权利,它用于控制用户对其他模式对象的访问。
5.2.3 管理系统权限
1.授予系统权限
GRANT 系统权限[, 系统权限, …]
TO {用户|角色|PUBLIC}[,{用户|角色|PUBLIC}]…
[WITH ADMIN OPTION];
2.撤销系统权限
REVOKE 系统权限[, 系统权限, …]
FROM {用户|角色|PUBLIC}[,{用户|角色|PUBLIC}]…
5.3 管理角色
角色是具有名称的一组相关权限的组合,即将不同的权限组合在一起就形成了角色。可以使用角色为用户授权,同样也可以从用户中回收角色。由于角色集合了多种权限,所以当为用户授予角色时,相当于为用户授予了多种权限。这样就避免了向用户逐一授权的繁琐,从而简化了用户权限的管理。数据库角色包含下列功能。
(1)一个角色可授予系统权限或对象权限。
(2)一个角色可授权给其他角色,但不能循环授权。
(3)任何角色可授权给任何数据库用户。
(4)授权给用户的每一角色可以是可用的或者不可用的。一个用户的安全域仅包含当前对该用户可用的全部角色的权限。
(5)一个间接授权角色对用户可显式地使其可用或不可用。
在一个数据库中,每一个角色名必须唯一。角色名与用户不同,角色不包含在任何模式中,所以建立角色的用户被删除时不影响该角色。
一般,建立角色服务有两个目的:为数据库应用系统管理权限和为用户组管理权限。相应的角色称为应用角色和用户角色。
应用角色是授予的运行数据库应用所需的全部权限。
用户角色是为具有公开权限需求的一组数据库用户而建立的。用户权限管理是受应用角色或权限授权给用户角色所控制,然后将用户角色授权给相应的用户。
第6章 数据库的安全保护
6.1 数据库安全性控制的方法和原理
安全性控制是指尽可能地杜绝所有可能的数据库非法访问。为了防止对数据库的非法访问,数据库的安全措施是一级一级层层设置的。其安全控制模型如图所示。
1.用户标识和鉴别
用户标识(Identification)和鉴别(Authentication)是数据库系统提供的最外层安全保护措施。其方法是由系统提供一定的方式让用户标识自己的身份,每次用户要求进入时,系统通过鉴别后才提供系统使用权。
常用的方法有以下几种。
(1)用户标识。
(2)口令。
(3)还可以使用磁卡或IC卡,但系统必须有阅读磁卡或IC卡的装置。还可以使用签名、指纹、声波纹等用户特征来鉴别用户身份。
2.存取控制
数据库安全性所关心的主要是DBMS的存取控制机制。
DBMS的存取控制机制主要包括两个部分:用户权限定义和合法权限检查。
6.2 Oracle系统的安全措施
1.Oracle 11g的安全性体系
Oracle 11g的安全性体系包括以下几个层次。
(1)物理层的安全性。数据库所在节点必须在物理上得到可靠的保护。
(2)用户层的安全性。哪些用户可以使用数据库,使用数据库的哪些对象,用户具有什么样的权限等。
(3)操作系统的安全性。数据库所在主机的操作系统的弱点将可能提供恶意攻击数据库的入口。
(4)网络层的安全性。Oracle 11g 主要是面向网络提供服务,因此,网络软件的安全性和网络数据传输的安全性是至关重要的。
(5)数据库系统层的安全性。通过对用户授予特定的访问数据库对象的权利的办法来确保数据库系统的安全。Oracle 11g包括角色、系统权限、对象权限和配置文件等内容,通常所说的Oracle 11g的安全性就是指数据库系统层的安全性。
2.Oracle 11g的安全性机制
Oracle 11g数据库系统层的安全机制可以分为两种:系统安全机制和数据安全机制。
6.3 数据库的完整性控制
6.3.1 完整性约束条件
完整性约束条件作用对象可以是关系、元组、列。其中列约束主要是列的数据类型、取值范围、精度、是否为空等;元组约束是元组之间列的约束关系;关系约束是指关系中元组之间以及关系和关系之间的约束。
完整性约束条件涉及的这3类对象,其状态可以是静态的,也可以是动态的。所谓静态约束是指数据库每一确定状态时的数据对象所应满足的约束条件,它是反映数据库状态合理性的约束,这是最重要的一类完整性约束。动态约束是指数据库从一种状态转变为另一种状态时新、旧值之间所应满足的约束条件,它是反映数据库状态变迁的约束。
综合静态和动态约束两个方面,可以将完整性约束条件分为6类。
1.静态列约束
静态列约束是对一个列的取值域的说明,这是最常用也最容易实现的一类完整性约束,主要有以下几个方面。
(1)对数据类型的约束。
(2)对数据格式的约束。
(3)对取值范围或取值集合的约束。
(4)对空值的约束。
2.静态元组约束
一个元组是由若干个列值组成的,静态元组约束就是规定元组的各个列之间的约束关系。例如,定货关系中包含发货量、定货量,规定发货量不得大于定货量。
3.静态关系约束
在一个关系的各个元组之间或者若干关系之间常常存在各种联系或约束。常见的静态关系约束有实体完整性约束、参照完整性约束、域完整性约束和用户定义完整性。
4.动态列约束
动态列约束是修改列定义或列值时应满足的约束条件,包括以下两个方面。
(1)修改列定义时的约束。
(2)修改列值时的约束。
5.动态元组约束
动态元组约束是指修改元组的值时,元组中各个字段间需要满足某种约束条件。
6.动态关系约束
动态关系约束是加在关系变化前后状态上的限制条件,例如事务一致性、原子性等约束条件。
6.3.2 完整性控制
DBMS的完整性控制机制应具有3个方面的功能。
(1)定义功能。提供定义完整性约束条件的机制。
(2)检查功能。检查用户发出的操作请求是否违背了完整性约束条件。
(3)保护功能。如果发现用户的操作请求使数据违背了完整性约束条件,则采取一定的动作来保证数据的完整性。
6.3.3 Oracle系统的完整性约束
(1)域完整性。
域完整性是对数据表中字段属性的约束,包括字段的值域、字段的类型及字段的有效规则等约束,是由确定关系结构时所定义的字段的属性决定的。
域完整性主要通过如下3种约束来实现:NOT NULL(非空)约束;UNIQUE (唯一性)约束;CHECK约束。
2)实体完整性。
实体完整性即指关系中的主属性值不能为NULL且不能有相同值。实体完整性是对关系中的记录唯一性,也就是主键的约束。
实体完整性约束就是定义主键,并设置主键不为空(NOT NULL)。
(3)参照完整性。
参照完整性指关系中的外键必须是另一个关系的主键有效值,或是 NULL。参照完整性是对关系数据库中建立关联关系的数据表间数据参照引用的约束,也就是对外键的约束。
6.4 数据库的并发性控制
数据库的并发控制和恢复技术与事务密切相关,事务是并发控制和恢复的基本单位。
6.4.1 事务
事务(Transaction)是用户定义的一个数据库操作序列,要么执行全部操作,要么一个操作都不执行,是一个不可分割的工作单元。一个事务由应用程序中的一组操作序列组成,在关系型数据库中,它可以是一条SQL语句、一组SQL语句或一个程序段。事务是这样一种机制,它确保多个SQL语句被当作单个工作单元来处理。
在SQL语言中,事务控制的语句有BEGIN TRANSACTION、COMMIT、ROLLBACK。如果用户没有指明事务的开始和结束,DBMS将按缺省规定自动划分事务。用户以BEGIN TRANSACTION开始事务,以COMMIT 或ROLLBACK 结束事务。COMMIT 表示提交事务,用于正常结束事务。ROLLBACK表示回滚,在事务执行过程中发生故障,事务不能继续时,撤消事
事务的性质
事务具有4个特性:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持续性(Durability),简称为ACID特性。
6.4.2 封锁
封锁就是事务T在对某个数据对象操作之前,先向系统发出请求,对其加锁。加锁后事务T就对该数据对象有了一定的控制,在事务T释放它的锁之前,其他的事务不能更新此数据对象。
1.封锁类型
按照锁的权限来分,基本的封锁类型有2种:排他锁(Exclusive Locks,简记为X锁)和共享锁(Share Locks,简记为S锁)。
排他锁又称为写锁。
如果事务T对某个数据D(可以是数据项、记录、数据集乃至整个数据库)加上X锁,那么只允许T读取和修改D,其他任何事务都不能再对D加任何类型的锁,直到T释放D上的锁。这就保证了其他事务在T释放D上的锁之前不能再读取和修改。
共享锁又称为读锁。
若事务T对某个数据D加上S锁,则事务T可以读D,但不能修改D,其他事务只能再对D加S锁,而不能加X锁,直到T释放D上的S锁。这就保证了其他事务可以读D,但在T释放D上的S锁之前其他事务不能对D做任何修改。
2.封锁协议
在运用X锁和S锁这两种基本封锁对数据对象加锁时,还需要约定一些规则,例如,何时申请X锁或S锁、持锁时间、何时释放等,我们称这些规则为封锁协议(Locking Protocol)。对封锁方式规定不同的规则,就形成了各种不同的封锁协议。下面介绍三级封锁协议。对并发事务的不正确调度可能会带来丢失更新、读“脏”数据和不可重复读等不一致性问题,三级封锁协议分别在不同程度上解决了这些问题,为并发事务的正确调度提供一定的保证。
(1)一级封锁协议。
事务T在修改数据D之前必须先对其加X锁,直到事务结束(包括正常结束COMMIT和非正常结束ROLLBACK)才释放,这称为一级封锁协议。一级封锁协议可防止丢失更新,并保证事务T是可恢复的。
在一级封锁协议中,如果仅仅是读数据不对其进行修改,是不需要加锁的,所以它不能保证不读“脏”数据和可重复读。
(2)二级封锁协议。
二级封锁协议是指在一级封锁协议的基础上,当事务T在读取数据D之前必须先对其加S锁,读完后即可释放S锁。二级封锁协议除防止了丢失更新,还可进一步防止读“脏”数据。由于读完后即可释放S锁,所以不能保证可重复读。
(3)三级封锁协议。
三级封锁协议是指一级封锁协议加上事务T在读取数据R之前必须先对其加S锁,直到事务结束才释放。三级封锁协议除防止了丢失更新和不读“脏”数据外,还进一步防止了不可重复读。
3.活锁和死锁
(1)活锁。系统可能使某个事务永远处于等待状态,得不到封锁的机会,这种现象称为“活锁”(Live Lock)。解决活锁问题的一种简单的方法是采用“先来先服务”的策略,也就是简单的排队方式。
(2)死锁。系统中有两个或两个以上的事务都处于等待状态,并且每个事务都在等待其中另一个事务解除封锁,它才能继续执行下去,结果造成任何一个事务都无法继续执行,这种现象称系统进入了“死锁”(Dead Lock)状态。
6.4.3 Oracle系统的并发控制技术
实现Oracle的并发控制需要依赖于封锁机制。按照锁所分配的资源来划分,Oracle中的锁共有3种:DML锁(数据锁);DDL锁(数据字典锁);Internal locks and latches。
(1)DML锁用于保护修改的数据不被其他事务并发修改,从而实现数据的完整性和一致性。DML锁又分为TM(表锁)和TX(行锁)。TX锁用于锁住修改的记录,防止其他事务同时修改, TM锁用于锁住被修改的表,防止其他事务对此表执行DDL语句修改表的结构。在用户发出DML命令时,Oracle会自动对其影响的记录和表加上TX锁及TM锁。
(2)DDL锁用于保护数据对象的结构不被其他事务修改。
(3)Internal locks and latches用于保护数据库内部结构不被修改。
这里只讨论DML锁DDL锁。通过查询动态字典视图V$lock,可以得到数据库中TM锁及TX锁的信息。
下面介绍加锁的方法。
1.行共享锁RS
对数据表定义行共享锁后,如果被事务A获得,那么其他事务可以进行并发查询、插入、删除及加锁,但不能以排他方式存取该数据表。执行下面的程序可以实现向数据表增加行共享锁。
LOCK TABLE student IN ROW SHARE MODE;
2.行排他锁RX
对数据表定义行排他锁后,如果被事务A获得,那么A事务对数据表中的行数据具有排他权利。其他事务可以对同一数据表中的其他数据行进行并发查询、插入、修改、删除及加锁,但不能使用以下3种方式加锁:行共享锁;共享行排他锁;行排他锁。执行下列语句可定义行排他锁。
LOCK TABLE student IN ROW EXCLUSIVE MODE;
3.共享锁S
对数据表定义共享锁后,如果被事务A获得,其他事务可以执行并发查询和加共享锁但不能修改表,也不能使用以下3种方式加锁:排他锁;共享行排他锁;行排他锁。执行下列语句定义共享锁。
LOCK TABLE student IN SHARE MODE;
4.共享行排他锁SRX
对数据表定义共享行排他锁后,如果被事务A获得,其他事务可以执行查询和对其他数据行加锁,但不能修改表,也不能使用以下4种方式加锁:共享锁;共享行排他锁;行排他锁;排他锁。执行下列语句定义共享行排他锁。
LOCK TABLE student IN SHARE ROW EXCLUSIVE MODE;
5.排他锁X
排他锁是最严格的锁。如果被事务A获得,A可以执行对数据表的读写操作,其他事务可以执行查询但不能执行插入、修改和删除操作。执行下列语句定义排他锁。
LOCK TABLE student IN EXCLUSIVE MODE;
6.4.4 Oracle系统的备份与恢复技术
1.RMAN
2.expdp/impdp
第7章 Oracle模式对象的管理
7.1 索引
索引是对数据库表中一个或多个列的值进行排序的一种结构,每个索引都有一个索引键与表中的记录关联,主要目的是加快数据的读取速度和完整性检查。建立索引是一项技术性要求高的工作。Oracle数据库会为表的主键和包含唯一性约束的列自动创建索引。
一般来说,创建索引要遵循以下原则。
• 如果每次查询仅选择表中的少量行,应该建立索引。
• 如果在表上需要进行频繁的DML操作,不要建立索引。
• 尽量不要在有很多重复值的列上建立索引。
• 不要在太小的表上建立索引。在一个小表中查询数据时,速度可能已经足够快,如果建立索引,对查询速度不仅没有多大帮助,反而需要一定的系统开销。
1.B*树索引
B树索引是以 B树结构组织并存放索引数据的,它是最常用的索引类型,默认情况下索引数据是以升序方式排列的。如果表包含的数据非常多,并且经常在WHERE子句中引用某列或某几列(列的重复值很少),则应该基于该列或该几列建立B树索引。B树索引由根节点、分支节点和叶子节点3部分组成,其结构如图所示。每个叶子节点就是所说的一个索引项,它又由3部分构成:头、键列和ROWID。键列即是索引列,将键列和相应的ROWID一起存储,这样,在找到相应的键时,就能直接根据ROWID找到相应的某行数据。
B树索引适用于具有高基数的字段,即大部分值都不相同的字段。创建B树索引的语法如下。
CREATE [UNIQUE] INDEX [模式名.]索引名
ON [模式名.]表名(字段名[ASC|DESC] [,字段名[ASC|DESC]]…)
[TABLESPACE 表空间名]
[PCTFREE][INITRANS][MAXTRANS][STORAGE CLAUSE][LOGGING|NOLOGGING]
其中,TABLESPACE参数用于指定表所属的表空间。PCTFREE参数用于设置在索引初始创建时指定Oracle块所预留的最小空闲空间的百分比。
INITRANS和MAXTRANS参数用于指定同一个块所允许的初始并发事务数(INITRANS)和最大并发事务数(MAXTRANS)。
STORAGE CLAUSE包括对区的参数设置,LOGGING和NOLOGGING表示是否日志文件。
2.位图索引
在位图索引中,使用一个比特位来对应一条记录的 ROWID,并通过位图索引映射函数来实现比特位到ROWID的映射。每个索引条目都有一个键值和ROWID组成。Oracle数据库中每一行都用 ROWID 来标志,ROWID 告诉数据库这一行的准确位置(指出行所在的文件、该文件的块、该块中的行地址)。创建位图索引的语法如下。
CREATE BITMAP INDEX [模式名.]索引名
ON [模式名.]表名(字段名[ASC|DESC] [,字段名[ASC|DESC]]…)
[TABLESPACE 表空间名]
[PCTFREE][INITRANS][MAXTRANS][STORAGE CLAUSE][LOGGING|NOLOGGING]
3.反向索引
反向索引是索引列值按照相反顺序存放的索引。
4.基于函数的索引
函数索引是基于函数或表达式所建立的索引。
7.2 分区表与分区索引
7.2.1 分区的概念
分区是指将巨型的表或索引分割成相对较小的、可独立管理的部分,这些独立的部分称为原来表或索引的分区。
1.分区键
在分区表中的每行都明确分给单个分区。分区键是为每行确定分区的列的集合。Oracle通过使用分区键自动将Insert、Update和Delete操作应用于分区。一个分区键包含1-16列的顺序列表;不能包含LEVEL、ROWID、MLSLABEL假列或者列的类型为ROWID;能够包含NULL值的列。
2.分区表
分区表是指按照特定方式逻辑划分大表,最终将其数据部署到几个相对较小的分区段中。执行SQL语句访问分区表时,服务器进程可以直接访问某个分区段,而不需要访问整张表的所有数据,从而降低磁盘 I/O,提高系统性能。表能够分区成任何数量的不同分区,除包含LONG和LONGRAW数据类型的表以外,都能够进行分区,对于包含CLOB和BLOB的表也能够分区。
3.分区索引组织表
管理员可以分配分区索引表。这种特性非常有用,因为它可以改善管理性、可用性和性能。而且,使用索引组织的表能够充分利用分区存储数据,例如图像和多媒体。
7.2.2 建立分区表
1.范围分区
范围分区基于分区字段值的范围将数据映射到所建立的分区上。这是最通用的分区类型,经常使用日期字段来分区。当使用范围分区的时候,需要记住以下几条规则。
(1)每个分区都包含VALUES LESS THAN字句,定义了分区的上层边界。任何等于和大于分区键值的二进制值都被添加到下一个高层分区中。
(2)所有的分区,除了第一个,如果低于VALUES LESS THAN所定义的下层边界,都放在前面的分区中。
(3)MAXVALUE可以用来定义最高层的分区。MAXVALUE表示了虚拟的无限值。
2.列表分区
列表分区可以控制如何将行映射到分区中去。可以在每个分区的字段上定义离散的值,这与范围分区和Hash分区是不同的。范围分区与分区相关联,Hash函数控制了行-分区的映射。列表分区的优点在于按照自然的方式将无序和没有关系的数据集合分组。
3.散列分区
如果分区字段的值不是数字、日期等类型,并且分区字段的取值范围也不固定,则可以考虑用Hash分区。Hash分区利用Oracle自带的Hash函数计算分区字段,并依据计算结果来对数据进行分区。因为语法很简单,因此 Hash 分区能够很容易对数据进行分区。在下面这种情况下,使用Hash分区比范围分区更好。
(1)当事先不知道需要将多少数据映射到给定的范围的时候。
(2)分区范围的大小很难确定,或者很难平衡的时候。
(3)范围分区使数据得到不希望的聚集时。
4.组合分区
组合分区使用范围方法分区,在每个分区中使用 Hash 方法进行子分区。组合分区比范围分区更容易管理,充分使用了 Hash 分区的并行优势。组合分区支持历史操作,如添加新的范围分区,同时为DML操作提供更高层的并行性。
7.2.3 分区索引
在Oracle中,可以为分区表建立3种类型的索引:局部分区索引、全局分区索引和非全局分区索引。对于全局分区索引,其索引数据会存放在一个索引段中;而对于局部分区索引,则索引数据会被存放到几个索引分区段中。
1.局部分区索引
局部分区索引是为分区表中的各个分区单独地建立分区,各个索引分区之间是相互独立的。局部分区索引比其他类型的分区索引更容易管理,提供了很高的可用性,在决策支持系统环境中非常通用。这是因为局部索引的每个分区与表的一个分区相关联,这使得Oracle能够自动保持索引分区与表分区同步。任何一个分区数据不合法或者不可用的活动都会影响单个分区。
局部分区索引可以是唯一的。然而,为了让局部分区索引保持唯一,表的分区字段必须是索引键列。局部分区索引与分区表的对应关系如图所示。
2.全局分区索引
全局分区索引是对整个分区表建立的索引,然后再由Oracle对索引进行分区。全局分区索引的各个分区之间不是相互独立的,索引分区与分区表之间也不是简单的一对一关系。图所示为全局分区索引与分区表的对应关系。
全局分区索引分区程度上是灵活的,其分区键与表的分区方法相独立。在OLTP环境中,全局分区索引非常通用,为访问单个记录提供了高效的方式。全局分区索引的最高层分区必须包含一个分区边界,索引的值是MAXVALUE。这保证表的所有行能够在索引中描述。
不能向全局分区索引添加分区,因为最高层的分区包含一个MAXVALUE分区边界。如果希望添加新的最高层分区,可以使用ALTER INDEX…SPLIT PARTITION语句。如果全局索引分区为空,可以使用ALTER INDEX DROP删除它。如果全局索引分区包含数据,删除分区将导致下一个最高层分区不可用。因此,在全局索引中不能删除最高层分区。
在Oracle中,可以在SQL语句中附加UPDATE GLOBAL INDEXES子句维护全局分区索引。这有两个优势,一是在操作过程中,索引保持可用,其他应用不会被这个操作影响;二是在操作以后,不用重建索引。
3.全局非分区索引
全局非分区索引类似于非分区索引,就是对整个分区表建立索引,但是未对索引进行分区。在OLTP环境中很常见,在访问单个记录的时候非常有效。图所示为全局非分区索引和分区表之间的关系。
7.3 外部表
外部表是Oracle提供的可读取操作系统文件数据的一种只读表,即外部表是表结构被存储在数据字典中,而表数据被存放在操作系统文件中的表。通过外部表,不仅可以在数据库中查询操作系统文件的数据,还可以使用 INSERT 方式将操作系统文件数据装载到数据库中,从而实现SQL*Loader所提供的功能。建立外部表后,可以查询外部表的数据,在外部表上执行连接查询,或对外部表的数据进行排序。需要注意,在外部表上不能执行 DML 修改,也不能在外部表上建立索引。
7.4 临时表
临时表用于存放会话或事务的私有数据。建立临时表后,其结构会一直存在,但其数据只在当前事务内或当前会话内有效。需要注意,当在临时表上执行 DML 操作时,既不会加锁,也不会将数据变化写到重做日志中。
7.5 簇与簇表
簇是一种用于存储数据表中数据的方法。簇实际上是一组表,由一组共享相同数据块的多个表组成。
7.6 序列
每个表都有一个可自动增长的字段,但是在Oracle中将自动增长的字段单独提取成一个数据库模式对象,称为序列(Sequence)。序列是Oracle提供的用于生成一系列唯一数字的数据库对象。序列会自动成生顺序递增的序列号,以实现自动提供唯一的主键值。序列可以在多用户并发环境中使用,并且可以为所有用户生成不重复的顺序数字,而不需要任何额外的I/O开销。
语法如下:
CREATE SEQUENCE 序列名
[START WITH 初始值]
[INCREMENT BY 步长值]
[MINVALUE 最小值| NOMINVALUE]
[MAXVALUE 最大值| NOMAXVALUE]
[CACHE 内存块的大小| NOCACHE]
[CYCLE | NOCYCLE]
[ORDER | NOORDER];
7.7 同义词
Oracle支持为表、索引或视图等模式对象定义别名,也就是为这些对象创建同义词。通过为模式对象创建同义词,可以隐藏对象的实际名称和所有者信息;或者隐藏分布式数据库中远程对象的位置信息,由此为对象提供一定的安全性保证;简化SQL语句。与视图、序列一样,同义词只在Oracle数据库的数据字典中保存其定义描述,因此同义词并不占用任何实际的存储空间。
Oracle中的同义词主要分为如下两类。
(1)公有同义词。被PUBLIC用户所拥有,数据库中的所有用户都可以使用公有同义词。
(2)私有同义词。由创建它的用户私人拥有。不过,用户可以控制其他用户是否有权使用自己的同义词。