Oracle9i数据库结构
谈及Oracle数据库结构时,我们应该从两个角度来探讨:分别是数据库的「逻辑层面」与「实体组成」。简单的说,「逻辑层面」是由”数据库内部”观看其组成要素,包括:资料表空间(tablespaces)、区段(segments)、延伸区块(extents)、资料区块(data block)、以及纲要对象(Schema objects)(注[1])。而「实体组成」则是从”操作系统”角度来看 Oracle9i 数据库的实体构成项目,包括:数据文件(Data files)、重置日志文件(redo log files)、控制文件(control files)、密码文件(password)、起始参数档(initialization parameter files)…等等。如果您有心成为一个顶尖的 Oracle DBA,那么不仅要对以上各项如数家珍般熟悉,还要了解其内部运作与相互关系才行。首先我们就先从「逻辑层面」探访Oracle9i数据库!
数据库之逻辑组成
无论是任何规模的企业,在管理数据库系统时,DBA都应该依据实际系统需求或是未来可能的管理方式,规划出一个或多个资料储存区域。重点是希望将资料分门别类地妥善存放。譬如,您可能会希望将公司内会计系统的帐务资料与产品销售纪录分开存放。
Oracle9i数据库允许DBA自行规划各种用途的资料表空间(Tablespace),以便存放不同型态的资料与数据库对象。举例来说,存放Oracle系统信息的「资料辞典」(data dictionary)可放在 SYSTEM 资料表空间;应用系统资料可存放在 USER 资料表空间;而所有数据表的索引(Index)则可单独存放在INDX 数据表空间内(注[2])。
一般来说,Oracle9i数据库至少应规划出五个以上的资料表空间,如下图一所示:
图一:Oracle9i数据库之资料表空间。
那么,先从资料的最小储存单位—「资料区块」谈起。
何谓「资料区块」?
许多初次接触数据库的读者最好奇的一点是:” 资料究竟是如何存放在数据库呢?”。其实,Oracle9i 数据库有几种资料储存体,其中最小的储存单元就称为「数据区块」(data block)。资料区块大小是由起始参数档的 DB_BLOCK_SIZE 参数所决定,且在新建Oracle9i数据库之前就必须明确地定义。实际上,资料区块大小与”操作系统的磁盘读写区块”(O.S. blocks)也有关系,所以您必须将 DB_BLOCK_SIZE 设定为 O.S. blocks的整数倍。附带一提:Oracle9i在存取资料时是以data block为最小读取单位,而不是以OS block为单位。
从 Oracle9i 开始,数据库内可以设定多种资料区块大小。换句话说,Oracle9i数据库内分为「标准资料区块」与「非标准资料区块」;预设情况下 SYSTEM 资料表空间就是以「标准资料区块」建立而成。
何谓「延伸区块」?
除了资料区块之外,Oracle9i数据库还有所谓的「延伸区块」(extents)。虽然资料区块是Oracle9i最小的资料读写单位,但值得注意的是:Oracle9i 在”配置”储存空间时,并不是以资料区块为单位,而是改采「延伸区块」的方式来配置空间。那么,使用「延伸区块」究竟有何好处呢?当您执行DDL指令建立数据库对象时(例如CREATE TABLE 指令),Oracle9i会先配置出一连串的资料区块;直到这些资料区块全部存满资料后,下次再配置一连串的资料区块。这些连续的资料区块就统称为「延伸区块」。
举例来说,假定您准备在Oracle9i数据库内存放80 KB的资料,Oracle9i可以先配置一个「延伸区块」,其大小可为资料区块(8 KB)的5倍;然后视实际需要再配置第二个「延伸区块」(大小还是40 KB)。如此一来,只要两次的空间配置动作就可以存放80 KB的资料了!试想,如果Oracle9i每次只配置8 KB的「资料区块」让您存放资料,总共需要10次空间配置动作才能放满80 KB的资料,是不是比较没有效率呢?由此可见,「延伸区块」的确有其存在的必要性。
何谓「区段」?
依照不同的数据处理性质,您可能需要在资料表空间内划分出不同区域,以存放不同资料;我们将这些区域称之为「区段」(segment)。例如,存放数据的称为「数据区段」、存放数据的称为「索引区段」。而「区段」其实就是由许多「延伸区块」组合而成。除了上述两种「区段」以外,Oracle9i数据库内还有另外两种区段结构,分别是:「暂时性区段」(temporary segment)与「退回区段」(rollback segment)。下图二说明了Oracle9i数据库内各逻辑组成要件之间的阶层关系:
图二:Tablespace、Segment、Extent、Block之间的关系。
所以,从Oracle9i数据库的「逻辑层面」来看,我们知道:
- n 资料是存放在每个「资料区块」内,资料读写动作也将以「资料区块」为单位。
- n 空间配置的动作则是引用「延伸区块」的概念。一个「延伸区块」由一连串的「资料区块」所构成。
- n 依实际资料量多寡,资料(或数据库对象)由多个「延伸区块」所组成。
- n 「资料表空间」内可划分不同的「区段」;而每个「区段」内又包含许多「延伸区块」。
- n 在每个Oracle9i数据库内可规划不同的「资料表空间」,用以存放不同型态的资料。
截至目前为止,无论是资料区块、延伸区块、区段、甚至数据表空间,都只是逻辑上的数据储存概念。实际上,Oracle9i数据库是藉由数个操作系统内实体档案来维系数据库系统之正常运作。接下来我们将从操作系统角度来探讨Oracle9i的实体组成要素。
数据库之实体组成
还记得上一期文章中我们曾经综览Oracle9i 服务器基本架构吗?如果从操作系统的观点来看,Oracle9i 数据库的实体组成要素就是操作系统内各式档案,最重要的有:数据文件、重置日志文件、控制文件、起始参数档…等。下图三描述了Oracle9i 数据库的基本架构。
图三:Oracle9i 数据库基本架构。
数据文件
每个 Oracle9i 数据库都包含为数不等的实体「数据文件」。数据库内所有逻辑数据库对象都是存放在数据文件内,如:数据表、索引….等。
一但数据文件被建立后,系统就会在磁盘上配置出适当空间给数据文件;但尚未存放任何使用者资料。等到未来使用者将资料存入数据库时,Oracle9i 才会在数据文件内配置出「数据区段」,以存放数据。而这些动作都是由 Oracle9i 自动完成的。
当然了,如果数据文件剩余空间不足,您就必须调整数据文件大小;或增加新的数据文件。所以在 Oracle9i 数据库内,一个数据库对象有可能横跨多个数据文件 (数据文件相关的管理与维护动作将在未来专栏内容中详细探讨) 。
如前所述,Oracle9i 数据库内可规划一个以上的「资料表空间」。但如果由操作系统角度来看,「资料表空间」其实是由一个或数个实体「数据文件」所组成。换句话说,数据库的所有资料就是位于操作系统的各「数据文件」内。
所以:
- n 一个「数据文件」只能对应的一个「资料表空间」。
- n 一个「资料表空间」可包含多个「数据文件」。
如下图四所示:SYSTEM 「资料表空间」对应到操作系统的 system01.ora 「数据文件」(注[3]);USER 「资料表空间」则是包含 user01.ora 与 user02.ora 两个「数据文件」。
图四:资料表空间与数据文件之对应。
重置日志文件
除了「数据文件」外,最重要的Oracle9i数据库实体档案就是「重置日志文件」(redo log files),也就是大家俗称的「交易日志」(transaction log)。虽然它与「数据文件」不同,但是彼此间却有密不可分的关系!简单的说,Oracle9i 重置日志文件会负责纪录数据库内任何数据处理情况(注[4])。当资料被异动时,所有异动纪录会先保留在内存的重置纪录缓冲区,并在适当时机由LGWR背景处理程序负责写入至硬盘上重置日志文件(注[5])。如此一来,所有资料异动情况都会完整地保留下来。万一您的 Oracle9i 数据库不小心当机或是遭遇毁损,Oracle9i 将凭借重置日志文件内相关纪录将资料复原至最完整的状态—这个动作我们又称为『Roll Forward』。
重置日志文件的配置方式
请注意,Oracle9i数据库正常运作的先决条件是至少配置两个(组)重置日志文件!
假定目前Oracle9i数据库拥有两个重置日志文件,分别是redo01.ora与redo02.ora。因为重置日志文件是以循环方式使用,所以当redo01.ora写满后就会轮到redo02.ora —这个动作称为「日志切换」(log switch)。理论上,当redo02.ora写满后应该会立刻从redo01.ora重新开始写入动作。但实际上并非如此— Oracle9i 会等到redo01.ora内纪录的资料异动情况真正反应在数据文件之后(记得我们曾经提过的CKPT处理程序吗?),才会覆写redo01.ora的资料。在一个大型线上交易(OLTP)系统下,如果资料交易量十分频繁,建议您不妨配置五个以上重置日志文件。以免Oracle9i进行「日志切换」时还要等候CKPT处理程序执行「检查点动作」(checkpoint),因而影响系统效能。
在执行关键性任务(mission-critical)的数据库系统中,为了避免硬件问题导致重置日志文件毁损(例如硬盘产生坏轨),我们会考虑建置「多重重置日志文件」(multiplexed redo log)。所谓的「多重重置日志文件」其实就是在其它硬盘内同时存放多份重置日志文件之复本。以下图五为例:假定原来的重置日志文件为Redo_A01.ora与Redo_A02.ora。我在第二个磁盘又额外规划了两个重置日志文件— Redo_B01.ora与Redo_B02.ora(分别为Redo_A01.ora与Redo_A02.ora之复本)。这时候Redo_A01.ora与Redo_B01.ora就构成所谓的「重置日志群组」(redo log group);而Redo_A01.ora与Redo_B01.ora分别为该群组之「群组成员」(member)。
一但您以「重置日志群组」的方式规划重置日志文件,LGWR会同时将异动纪录写入相同群组的所有成员。也就是说,LGWR会将资料同时写入Redo_A01.ora与Redo_B01.ora,等到发生「日志切换」动作后,再同时写入Redo_A02.ora与Redo_B02.ora。可想而知,万一这两颗硬盘其中之一不幸损毁。重置日志文件将不受任何影响。
尽管「多重重置日志文件」的概念已具备容错功能,但是对于重置日志文件之写入效能却有一定程度的影响!这也是我们在规划之初就必须考虑的重点之一。
图五:多重重置日志文件的配置方式。
控制檔
每个 Oracle9i 数据库也都会有一个「控制文件」,用以纪录与描述数据库的实体结构。「控制文件」内记录以下重要信息:
- n Oracle9i数据库名称与建立时间。
- n 数据文件与重置日志文件之名称,及其所在位置。
- n 交易纪录序列码(log sequence number)。
每当数据库被激活时,Oracle9i 会在执行个体激活后立刻读取控制文件内容,待所有数据库实体组成档案之所在信息都收集完毕,数据库才会被开启。为了避免控制档毁损导致数据库系统停摆,建议您比照「多重重置日志群组」的方式—至少配置两个控制文件,并存放在不同实体硬盘(注[6])。
起始参数档
在激活执行个体之前,Oracle9i必须依照特定参数设定值来配置内存空间,并激活相关背景处理程序。而DBA 可以事先规划这些参数,并存放在操作系统内的某个档案。往后将利用这个档案来开启相对应的Oracle9i 执行个体。这个档案就是所谓的「起始参数档」。
起始参数档包含以下主要内容:
- n 系统全域区相关的组态设定
- n 其它各起始参数之名称与设定值
- n 控制文件名称与存放路径
n 重置日志文件之相关设定
注[1]:Oracle9i的纲要对象即为俗称的”数据库对象”。
注[2]:SYSTEM为Oracle数据库预设的资料表空间;USER与INDX则是由DBA自行规划建置的。
注[3]:任何 Oracle9i 数据库都必须要有一个 SYSTEM 资料表空间,所以Oracle9i 会在建立数据库时自动将第一个数据文件配置给 SYSTEM 数据表空间。
注[4]:这里的数据处理动作泛指新增、修改、删除;但查询动作除外。
注[5]:有关重置纪录缓冲区与LGWR背景处理的互动过程,请参阅我在2002年1月Linuxer杂志的专栏文章。
注[6]:除了数据库激活时需读取控制档以外。进行数据库复原动作时也必须存取控制档内容。
您可以利用任何文字编辑器来建立或修改起始参数档,通常起始参数档的名称为init.ora或是init<SID>.ora。假定Oracle9i 执行个体的名称为ora901,起始参数档之档名就可以定为initora901.ora。以下是一个起始参数文件范例:
# Copyright (c) 1991, 2001 by Oracle Corporation # Cache and I/O db_block_size=8192 db_cache_size=67108864 # Cursors and Library Cache open_cursors=300 # Diagnostics and Statistics background_dump_dest=/opt/oracle/admin/ora901/bdump core_dump_dest=/opt/oracle/admin/ora901/cdump timed_statistics=TRUE user_dump_dest=/opt/oracle/admin/ora901/udump # Distributed, Replication and Snapshot db_domain=uuu.com.tw remote_login_passwordfile=EXCLUSIVE # File Configuration control_files=("/opt/oracle/oradata/ora901/control01.ctl", "/opt/oracle/oradata/ora901/control02.ctl", "/opt/oracle/oradata/ora901/control03.ctl") # MTS dispatchers="(PROTOCOL=TCP)(SER=MODOSE)", "(PROTOCOL=TCP)(PRE=oracle.aurora.server.GiopServer)", "(PROTOCOL=TCP)(PRE=oracle.aurora.server.SGiopServer)" # Miscellaneous compatible=9.0.0 db_name=ora901 |
# Network Registration instance_name=ora901 # Pools java_pool_size=117440512 large_pool_size=1048576 shared_pool_size=117440512 # Processes and Sessions processes=150 # Redo Log and Recovery fast_start_mttr_target=300 # Resource Manager resource_manager_plan=SYSTEM_PLAN # Sort, Hash Joins, Bitmap Indexes sort_area_size=524288 # System Managed Undo and Rollback Segments undo_management=AUTO undo_tablespace=UNDOTBS |
除了上述档案之外,Oracle9i 数据库内还包含密码文件(password file)、重置日志封存盘(Archived Redo log files)。有关这些档案的使用时机与管理方式将在未来专栏中陆续为大家深入介绍。
了解Oracle9i 数据库的实体组成后,我们就可以继续往下探讨Oracle9i 数据库的激活/关闭方式。
激活与关闭Oracle9i数据库
在激活Oracle9i数据库之前,首先您必须了解数据库的各种激活状态:
下表一列出不同的激活状态,与其使用时机:
激活状态 | 说明 |
NOMOUNT | - n 仅激活Oracle9i执行个体,不会挂载(mount)Oracle数据库。
- n 配置系统全域区(SGA),激活各背景处理程序。
- n 数据库尚无法使用。
- n DBA可执行ALTER DATABASE指令将数据库开启至MOUNT或是OPEN状态。
- n 通常使用于第一次建立数据库,或是需重建控制档时。
|
MOUNT | - n 激活Oracle9i执行个体。
- n 开启控制档。
- n 挂载Oracle9i数据库,但尚未开启之。
- n 数据库尚无法使用,但是DBA可以进行特殊的管理工作(例如更改数据库内重置日志文件的封存模式)。
|
OPEN | - n 激活Oracle9i执行个体。
- n 开启控制档。
- n 挂载Oracle9i数据库之后立刻开启。
- n 使用者可以存取数据库。
|
表一:Oracle9i数据库各种激活状态。
当您的系统内尚未建立任何数据库之前,只能先将Oracle9i执行个体开启至NOMOUNT状态,接着利用CREATE DATABASE指令建立Oracle9i数据库。待数据库顺利建立时(数据库内相关的信息已纪录至控制文件),才可以执行ALTER DATABASE指令将数据库开启至OPEN状态;或是先将执行个体关闭,再一口气将数据库开启至OPEN状态。
欲开启/关闭Oracle9i数据库时可利用以下几种工具:
- n SQL*Plus。
- n Oracle Enterprise Manager。
- n Recovery Manager。
一般来说,前两种是比较常用的方式。值得注意的是:在Oracle8i之前版本可使用Server Manager来激活/关闭Oracle数据库,或是执行系统维护的相关指令。从Oracle8i以后,所有Server Manager的指令都可以在SQL*Plus下执行。而Oracle9i已移除Server Manager,统一由SQL*Plus做为Oracle9i的客户端工具。
激活Oracle9i数据库的方式
欲开启Oracle9i数据库之前,您必须先以SYSDBA身分登入,然后执行STARTUP指令。下列步骤假设您是从SQL*Plus激活数据库:
$ sqlplus /nolog
这里我们使用了 nolog 选项,这是假设目前 Oracle9i 数据库尚未激活,当然也无法登入数据库。所以我们仅先进入SQL*Plus环境。
SQL> connect使用者名称/密码as sysdba
STARTUPPFILE = 起始参数档名称激活状态
例如:
STARTUPPFILE = initora901.oraNOMOUNT
在一般情况下,如果要将Oracle9i数据库开启至OPEN状态,可以直接执行STARTUP指令。
STARTUP
结果如下图五所示:
图五:利用SQL*Plus开启Oracle9i数据库至OPEN状态。
由图五可得知:激活Oracle9i 执行个体时会先配置出系统全域区,然后是挂载数据库,最后才会将数据库开启至OPEN状态。
关闭Oracle9i数据库的方式
关闭数据库时,您也必须以SYSDBA登入后执行SHUTDOWN指令。SHUTDOWN指令共有下列四种选项:
- n Normal
- n Transactional
- n Immediate
- n Abort
下表二整理出每个选项之用途与使用时机:
SHUTDOWN选项 | 说明 |
Normal | - n 其它使用者无法再登入数据库,但现有使用者可继续未完成的数据处理动作。Oracle9i会等待所有使用者离线后才关闭数据库。
- n 下次开启Oracle9i数据库时,系统不需进行执行个体修复动作(Instance Recovery)。
- n 为系统预设的关闭数据库选项。
|
Transactional | - n 不允许其它使用者再登入数据库。
- n 正在进行的资料交易动作不会受到影响。
- n 等到交易正常结束(不管是确认或是退回交易) Oracle9i才结束使用者联机阶段。待所有使用者离线后才关闭数据库。
- n 下次开启Oracle9i数据库时,系统不需进行执行个体修复动作。
|
Immediate | - n 不允许其它使用者再登入数据库。
- n 自动退回(rollback)所有未确认的交易
- n Oracle9i自动结束所有使用者联机阶段,并关闭数据库。
- n 资料交易的一致性与完整性可能会受到影响。
- n 下次开启Oracle9i数据库时,系统不需进行执行个体修复动作。
|
Abort | - n 不允许其它使用者再登入数据库。
- n 正在进行的所有交易会立刻中断(不会rollback)。
- n Oracle9i会自动中断所有使用者联机阶段。
- n 资料交易的一致性与完整性可能会受到影响。
- n 下次开启Oracle9i数据库时,系统会自动进行执行个体修复动作。
|
表二:Oracle9i数据库的关闭指令选项。
关闭数据库的方式如激活数据库的方式类似,您可以在登入SQL*Plus之后执行SHUTDOWN指令。结果如图六所示:
图六:关闭Oracle9i数据库。
通常我们都是以Normal或是Transactional来关闭数据库。除非必要,否则请尽量不要使用SHUTDOWN ABORT去关闭Oracle9i数据库,以免影响使用者正在进行的数据处理工作。
结语
在本期内容里,我以两种角度探讨了Oracle9i数据库的组成要素。个人认为这是学习Oracle最重要的工作。在我从事Oracle数据库管理相关教学工作以来,这部分也是上课学员普遍认为较难接受的观念之一。但是只要这些基本观念搞清楚,就像练武时任督二脉已被打通一般,未来研读Oracle的相关技术将会如鱼得水。最近也有读者来信和我讨论Oracle9i数据库的管理技巧。当然了,Oracle9i也有很棒的图形接口管理工具— Oracle9i Enterprise Manager。
未来的专栏内容我必然会为大家介绍Oracle9i Enterprise Manager的使用方式与技巧。有了Enterprise Manager,管理Oracle9i数据库将如虎添翼!