作者: 何致億, 美商甲骨文公司台湾分公司 特约顾问
前言
前两期的专栏内容已分别为大家介绍了 Oracle9i for Linux 的安装方式,以及Oracle9i 企业版概观。但是如何组态与管理 Oracle9i 数据库才是我们要讨论的重点。本文将深入探讨 Oracle9i Instance的组成要素与其运作原理,为您揭开 Oracle9i 的神秘面纱。
本文将涵盖以下主题:
Oracle9i 服务器架构简介。
何谓 Oracle9i Instance
系统全域区
背景处理程序
在开始任何Oracle9i数据库管理工作之前,您必须先熟悉 Oracle9i服务器之整体架构及其运作原理。所以我先为大家简介 Oracle9i 服务器的基本组成架构。
Oracle9i服务器架构
以Oracle9i数据库系统本身而言,大致上可区分为两个主要部分:
Oracle9i执行个体(Oracle9i Instance)
Oracle9i数据库档案(Database files)。
简言之,Oracle9i Instance 是指数据库服务器的内存与相关处理程序。您可以想象它就是Oracle9i的心脏。数据库实体则由操作系统内的各式档案组成。如果您想深入了解Oracle9i 系统运作或从事进阶的效能调校,那么一定要搞清楚这两部分彼此的互动关系才行!Oracle9i服务器基本架构如图1所示:
图1:Oracle9i 服务器基本架构。
图1上半部为内存内Oracle9i Instance,下半部则是位于操作系统的各种数据库档案(有关这些档案的细部信息将在下一期说明)。彼此之间是藉由各个背景处理程序互相沟通。
接下来我们先讨论Oracle9i Instance的组成要素。
何谓Oracle9i Instance?
第一次接触Oracle数据库的使用者经常对「Oracle Instance」这个名词感到混淆,因为Instance这个单字从字典上查到的意义跟数据库一点关系也没有!某些中文书译者喜欢将Oracle Instance译为「Oracle实例」,但是我认为这个译名十分不恰当!我个人比较倾向称它为「Oracle执行个体」;俗称「Oracle数据库引擎」。既然是数据库引擎,就表示Oracle数据库内大大小小的事都跟它有关系,当然这也是我们一开始就先讨论的主要原因啰。
Oracle9i 执行个体主要是由以下两项要素组成:
n 系统全域区(System Global Area)
n 背景处理程序(background processes)
来看看什么是「系统全域区」?
系统全域区
当您激活Oracle9i数据库时,系统会先在内存内规划一个固定区域,用来储存每位使用者所需存取的资料,以及Oracle9i运作时必备的系统信息。我们称此区域为系统全域区(System Global Area),俗称SGA (注1) 。
在 Oracle8i 时,SGA 的大小是由起始参数档(initialization parameter file )内的某些参数所设定。但最麻烦的是每次调整参数之后必须等重新激活数据库才生效(感觉就像在Windows系统修改了一些设定就要重新开机)。光是数据库的关闭与激活就花去不少时间(难怪大家羡幕 Oracle Consultant 很好赚….., just kidding!! ),何况是执行关键性任务的数据库哪能一天到晚开来关去!? 从 Oracle9i 开始,DBA 可以动态配置内存的大小;这样的技术我们称为「dynamic SGA」。有了dynamic SGA ,SGA 的各组成区域都可以动态地进行规划与调整,而不需先关闭数据库。
Tips: 起始参数档(Initialization Parameter file)之意义
如上所述,Oracle Instance被激活时,系统必须藉由某些参数值来配置适当大小的内存空间。换言之,我们可以在激活Instance之前就先规划这些参数的设定值,并储存在操作系统下的某个档案里。往后只要利用此档案就可开启相对应的Oracle Instance — 我们就将这个档案称之为起始参数档。
一般来说,我们还是应该在激活 Oracle9i 之前就妥善规划好适当的内存空间。例如,起始参数档的 SGA_MAX_SIZE(注2)可设定 SGA 所占用的最大内存空间。如果考虑 Oracle9i 的执行效能,理应将此参数尽可能设到最大!但有一点需要注意的是:SGA_MAX_SIZE 尽量不要超过物理内存大小,否则将会使用到硬盘上的虚拟内存,反而导致效能低落。
SGA 的大小可由起始参数档之特定参数所控制,表1整理出与SGA相关的参数名称及其意义:
注1:在多人使用的环境下,SGA 的资料可分享给所有同时上线的联机阶段使用,所以 SGA 有时也称为 Shared Global Area。
注2:如果 SGA_MAX_SIZE 之设定值小于其它 SGA 相关参数设定值的总和;或是小于各相关参数默认值的总和,则 SGA_MAX_SIZE 之设定值无效。
如图1所示,SGA又包含数个重要区域,分别是:
n Database Buffer Cache (资料快取缓冲区)
n Redo Log Buffer (重置日志缓冲区)
n Shared Pool (共享区)
n 其它,如Large pool
以下是每个区域之意义、用途,以及相关设定方式。
资料快取缓冲区
为SGA 的主要成员,用来存放读取自数据文件的资料区块复本,或是使用者曾经处理过的资料。其用途在于有效减少存取资料时造成的磁盘读写动作,进而提升资料存取之效能。所有同时上线的使用者都可以共享此缓冲区的资料。
整个资料快取缓冲区包含两种缓冲区串行,分别是 write list 与 LRU list:
n Write list 存放dirty buffers(注3)之复本,会在适当时机写入磁盘。
n LRU list 包含:free buffers,dirty buffers与pinned buffers。其中free buffer 为空白的缓冲区,随时可存放资料;pinned buffer则是目前使用中的缓冲区。
注3: dirty buffer 是存放”已修改,但尚未写入磁盘的数据”之缓冲区。
资料快取缓冲区运作原理
当使用者第一次向Oracle9i 送出资料查询请求时,Oracle9i 会先在资料快取缓冲区内寻找该资料。如果欲查询的资料恰好已存在于缓冲区内(这样的情况我们称之为 cache hit ),就直接从内存读出资料。
反之,如果缓冲区内并没有使用者欲查询的资料(此情况称为 cache miss ),Oracle9i就会先从磁盘上数据文件读出适当的数据区块,放入缓冲区之后,使用者才从缓冲区读取资料。您可以想象一下:在 “cache hit” 的情况下查询资料的速度是不是比在 ”cache miss” 的情况还快很多呢?事实上,这就是资料快取缓冲区的主要用途所在。
让我们进行更深入的讨论!
当资料区块从磁盘读出,准备放入缓冲区时,系统必须先确定资料快取缓冲区内有free buffers。这时候Oracle9i 会开始扫描 LRU list,扫描的原则为:
n 从 LRU 端扫到 MRU 端
n 当扫描到 free buffer;或是已扫描的缓冲区数目超过临界值时,就会停止扫描动作
n 扫描 LRU list 时如果发现了dirty buffer,就将它移到 write list,然后继续扫描
如果扫描过程顺利在LRU list 内找到 free buffer,那么Oracle9i就会把从磁盘读出的数据区块放入此 free buffer中,然后再把它移到 LRU list 的 MRU 端。
但是,如果 LRU list 真的都没有free buffer怎么办呢?那么Oracle9i 就会停止扫描动作,然后通知数据库写入器(database writer)背景处理程序将部分 dirty buffers 先写入磁盘,接着从 LRU list 的 LRU端开始清除缓冲区。如此一来就可以空出新的free buffer了。
Tips:LRU list 与 LRU 算法
所谓 LRU (least recently used)算法之基本概念为:当内存内剩余可利用的空间不足时,缓冲区尽可能先保留使用者最常使用的资料;换言之,优先清除”较不常使用的资料”,并释放其空间。我以图标方式为大家说明:
我们将 LRU list 想象成是长条型一连串的缓冲区集合,两端点分别为「MRU端」以及「LRU端」。所谓的「MRU」为「Most Recently Used」之缩写,我将之译为”最常使用的”(或是”最近使用的”)。所以,愈靠近MRU端的缓冲区,代表其为被使用者最近查询过的资料。同理,我们将「LRU」端视为”最不常被查询的资料(Least Recently Used)”,或是”很久都没被再次查询的资料”。如下图2中的 State 0 所示:(假设目前LRU list没有任何资料存放)
图2:LRU list第一种使用情况。
图2的State1、State2、State3仿真某个使用者欲从Oracle9i数据库查询出三笔资料(A资料、B资料、C资料)。这三笔数据从磁盘读出后,依序放入LRU list的free buffers。以State3为例:因为C资料是”最近刚刚使用”的资料,所以最靠近MRU端;相较之下,A资料是”有一段时间都没用的资料”,所以比较靠近LRU端。依此类推,如果使用者持续地查询资料或进行相关数据处理动作,则LRU list内的缓冲区都会被填满,如图2的State m所示:M资料填满最后一个free buffer。