五、oracle软体结构
总体说来oracle的软体结构是针对内存和进程而言的。在oracle中每个数据库至少有一个实例与之对应。启动数据库时首先是在内存中创建一个实例,然后由实例加载并打开数据库。当用户连接数据库时,实际上是连接到实例中,然后由实例负责与数据库通信进行交互工作。
Oracle实例主要由两部分组成:
l 实例的内存结构
l 实例的进程结构
1. 实例的内存结构
Oracle实例在启动时,在内存中创建一个内存结构用以保存数据库实例在运行过程中所处理的数据。
实例内存结构的划分:
l SGA区(系统全局区,system global area):其位于系统的共享内存段中,可以被所有的服务和后台进程共享。
l PGA区(程序全局区,program global area):保存的是某个服务进程私有的数据和控制信息。
其主要包括的数据有:
l 缓存的数据。
l 解析后sql或PL/SQL程序代码
l 数据库用户的会话信息
l 后台进程所需的共享信息和数据
a. SGA区
SGA区是oracle实例的主要组成部分。在这个区中保存着oracle系统和用户的共享信息。
其内存结构主要包括(参照上图):
l 数据库缓存-在缓冲区高速缓存中
l 重做日志缓存-在缓冲区高速缓存中
l 共享池-在共享池中
l Java池-在java池中
l 大型池-在大型池中
l 数据字典缓存-在共享池中
l 保存其他控制信息的结构-在共享池中
一般来说oracle会自动管理SGA区的各项参数。但是SGA区的整体大小不能超过初始化参数SGA_MAX_SIZE。
当然为了优化性能,最好将SGA区全部放在物理内存中,可以设置初始化参数LOCK_SGA为true来锁定其只能使用物理内存而不能使用虚拟内存。如图:
能够影响SGA区大小的初始化参数主要有:
l DB_CACHE_SIZE:设置数据库缓存大小
l LOG_BUFFER:设置从做日志缓存大小
l SHARED_POOL_SIZE:设置共享池大小
l LARGE_POOL_SIZE:设置大型池大小
当然假如你想用sql*plus查看一下当前SGA的分配情况,可以使用show sga命令,如图:
下面我们开始详细的讲一下SGA里的各个内存结构。
l 数据库缓存
顾名思义这个缓存区是用来保存最近从数据文件中读取的数据块的。为什么数据库都喜欢大内存?就是因为数据库喜欢将数据保存在内存中进行处理,毕竟在内存中进行处理要比在硬盘上处理要快的多。
数据库缓存块类型:
脏缓存块:保存已经修改过的数据,这些数据即将被保存到硬盘上了。
空闲缓存块:不包含任何数据
命中缓存块:正在被用户访问的缓存块
缓存块的管理方式:
脏缓存块列表:包含已经被修改并需要重新写入硬盘的缓存块
LRU列表:包含所有空闲缓存块,命中缓存块以及那些还没来得及移入脏缓存块列表的脏缓存块。
数据库缓存也被分为几个独立的缓存池:
KEEP缓存池:对应的初始化参数BUFFER_POOL_KEEP,在keep缓存池中的缓存块始终保留在数据库缓存中。
RECYCLE缓存池:对应的初始化参数BUFFER_POOL_RECYCLE,在recycle缓存池的缓存块一旦用完立即交给系统内存。
DEFAULT缓存池:DB_CACHE_SIZE减去上面2个参数值机为default缓存池大小,如果对象没有指定所使用的缓存池,他们的缓存块将放置在default缓存池中。
l 重做日志缓存
重做日志缓存位于SGA区中的缓存区,用于缓存在对数据进行修改的操作过程中生成的重做记录。重做日志缓存中的内容将被LGWR后台进程随时写入重做日志文件。
l 共享池
共享池是SGA区中的一系列内存结构,主要包括库缓存、数据字典缓存,以及用于存储并行操作信息和控制结构的缓存。
库缓存:用于缓存已经解析并执行过的sql和pl/sql程序代码。
数据字典缓存:保存最常使用的数据字典信息。
l 大型池
实际上是个备用池,用以缓解oracle对共享池和PGA区内存使用压力的。
b. PGA区
PGA区是保存有特定服务进程的数据和控制信息的内存结构,这个内存结构是非共享的,只有服务进程本身才能够访问它自己PGA区。
一般情况下,PGA区包含私有SQL工作区和会话内存区。
l 私有SQL工作区
当一个用户连接到数据库中时,oracle即创建一个会话,每个会话都对应于一个用户进程。在私有SQL工作区中包含有绑定变量以及SQL语句运行时的内存结构等信息。多条相同的SQL语句只会建立一个共享SQL工作区,共享SQL工作区是创建在SGA区的共享池中的。所以说一条完整的缓存数据是由一个私有SQL工作区和共享SQL工作区合并而成的。
私有SQL工作区又分为两个部分:
静态区:静态区中的内容在会话过程中始终保持不变,直到会话结束,才被释放。
动态区:动态区中的内容在会话过程中不断变化,一旦SQL语句执行完毕,即释放。
对于SQL工作区的内存分配,可以使用初始化参数PGA_AGGREGATE_TARGET设置,如下图
我设置成
这里要补充一句,以后和以前我所说的所有以初始化参数开头的参数都是可以在数据库配置界面中修改的。如下图(OEM界面),点击所有初始化参数按钮即可获得数据库配置界面。
l 会话内存区
用于保存用户会话的变量以及其他与会话相关的信息。
1. 实例进程结构
Oracle在工作过程中主要涉及到两类进程
l 用户进程:是在用户连接数据库时创建的,其不属于实例的组成部分,主要功能是完成用户所指定的任务。
l Oracle进程:oracle在创建实例时产生的,完成特定的任务。
Oracle进程包括:服务进程和后台进程。
a. 服务进程
主要完成的任务:
l 解析并执行用户所提交的SQL语句
l 在SGA区的数据库缓存中搜索用户进程访问的数据,如不存在则到硬盘上查找,并将其复制到内存中。
l 将数据返回给用户进程。
b. 后台进程
由于oracle属于大型数据库,所以可能会同时有大量的用户进程存在,为了时数据库始终保持良好的性能。所以oracle将很多的服务划分为单一的系统进程来专门处理。这些进程统称为后台进程。
后台进程主要包括:
l 数据库写进程(DBWR)
l 日志写进程(LGWR)
l 检查点进程(CKPT)
l 系统监视进程(SMON)
l 进程监视进程(PMON)
l 归档进程(ARCn)
l 恢复进程(RECo)
l 调度程序进程(Dnnn)
l 作业队列进程(CJQn)
l 队列监视进程(QMNn)
等等。
其中DBWR,LGWR,CKPT,SMON,PMON是必须的后台进程,其他都是可选进程。
a) DBWR
负责将数据库缓存中的脏缓存块成批写入到数据文件中。当数据修改操作很繁忙时Oracle最多允许9个额外DBWR进程(DBW1~DBW9)和一个主DBWR(DBW0)同时存在。
与DBWR相关的初始化进程:
l DB_WRITER_PROCESSES:设置创建实例时启动的DBWR进程数量。注意每个CPU对应一个DBWR进程,创建过多的DBWR进程一是没有用,二是消耗资源。
如图:
l DB_BLOCK_CHECKPOINT_BATCH:这个参数用于设置在每个检查点发生时,DBWR进程写入的脏缓存块的最大数目。图略
l DB_BLOCK_LRU_LATCHES:用于设置数据库缓存区LRU锁的数量。图略
b) LGWR
负责将重做日志缓存中的重做记录写入联机重做日志文件中。它比DBWR要简单得多,基本上不需要配置。
c) CKPT
检查点其实是一个事件,当该事件发生时,数据库缓存中的脏缓存块将被写入数据文件,同时oracle将对数据库控制文件和数据文件进行更新,以记录下当前的数据库结构和状态。
与CKPT相关的初始化参数:
LOG_CHECHPOINT_TIMEOUT:用于指定检查点执行的最大时间间隔。如设为0表示禁用基于时间的检查点。
LOG_CHECHPOINT_INTERVAL:用于指定在出现检查点之前,必须写入重做日志文件的操作系统块的数量。
LOG_CHECHPOINT_TO_ALERT:用于指定是否将检查点信息记录到警告日志中。
如图,我这边的3个参数和起来的意思就是:当重做日志写入
a) SMON
负责对数据库进行恢复操作,如果上次数据库是非正常关闭,则下次启动时SMON会自动读取重做日志文件,对数据库进行恢复。同时还负责在临时段或临时表空间中回收不再使用的存储空间和将各个表空间中的空闲空间碎片合并在一起。
b) PMON
负责对那些失败的用户进程或服务进程进行恢复,并释放进程占用的资源。
c) RECO
负责在分布式数据库环境中自动恢复那些失败的分布式事务。
d) ARCn
当数据库运行在归档模式下时,ARCn负责在日志切换后将已经写满的重做日志文件复制到归档目标中(独立硬盘,磁带机…)。
e) Dnnn
接受用户进程的请求,将它们放入请求队列中,然后为请求队列中用户进程分配一个服务进程。