最近,把Oracle concepts 又读了一遍,想翻译一下第7章 内存结构,在翻译的过程,发现真的很难翻译,很多词语用英文表达非常准确,翻译起来却不知道如何表达,想想以前对翻译者的评价,汗...,自己也一样翻译不好.本来想把全部翻译完再贴出来,不过一直断断续续的翻译进展不大.就先把自己已经翻译的贴出来,也算对自己的鼓励.
内存结构
- Oracle内存结构介绍
- 系统全局区(SGA)概述
- 程序全局区(PGA)概述
- Dedicated and Shared Servers
- Software Code Areas
- 程序代码
- 连接所有Session的信息,包括当前不活跃的Session
- 程序执行时所需要的信息(比如,当前查询的状态,哪些行数据已经被提取)
- Oracle进程间共享和通讯的信息 (比如,锁的信息)
- 发生改变的数据. (比如,数据块和重做日志记录)
- 系统全局区System Global Area (SGA), 系统全局区被所有的服务进程和后台进程所共享,他包括以下部分:
- 程序全局区Program Global Areas (PGA), 系统全局区对每个服务进程和后台进程是私有的,每个进程都有一个PGA区,PGA包括以下方面:
图 7-1 Oralce内存结构关系说明
Figure 7-1 Oracle Memory Structures
系统全局区是一组包含数据块和数据库实例控制信息的共享内存结构. 如果多个勇挑同时连接到一个数据块实例,系统全局区的数据会被每一个Session所共享.从而,SGA有时被叫做共享全局区(shared global area).
SGA区和Oracle的进程组成了Oracle的实例,Oracle实例启动时会自动分配SGA的内存,当数据库实例关闭时操作系统会回收相关的内存.每一个数据库实例都有自己的SGA.
SGA区是可读/写的.所有连接到多进程数据库实例的用户可以读到SGA的内容,有特定的几个进程在运行时将信息写入SGA区.
- 高速数据缓冲区(Database buffer cache )
- 重做日志缓冲区(Redo log buffer )
- 共享池(Shared pool )
- JAVA池(Java pool )
- 大池(Large pool (可选))
- 数据字典缓存(Data dictionary cache )
- 其它信息
SGA区的一部分包括后台进程需要访问的数据库实例和状态的数据; 这部分叫做固定SGA(fixed SGA).这里不允许用户数据的存储. SGA区还包含进程间通讯的信息,比如说锁相关信息.
如果系统用共享服务结构的数据库,那么PGA中请求和相应的队列和其它的一些信息,被存储到SGA区中.
|
利用动态SGA的结构,高速缓存区,共享池,大池,系统私有内存可以在不重新数据库的情况下动态改变..
动态SGA允许Oracle在运行时设置, Oracle如何使用虚拟内存. 可以启动一个没有配置的实例,并且允许实例使用超过最大值SGA_MAX_SIZE的内存.如果在初始化文件中指定SGA_MAX_SIZE参数小于所有SGA组件的和,那么这个参数的设置将会被忽略.
在系统调优时,SGA的尺寸应该与物理内存相适合,如果不适合,虚拟内存就会存储一部分SGA区的内容,那么整个系统的性能就会严重的下降,因为一部分SGA使用换页空间.对SGA区中的共享池也有影响.
SGA的尺寸被几个初始化参数控制.下面是影响SGA区大小的几个最重要的参数:
当用企业管理器或SQL PLUS启动Oracle时,改Oracle实例的SGA信息会显示在屏幕上,如果没有显示,你可以利用SQL*Plus Show SGA 语法来显示SGA的大小.
对于动态SGA,动态可分配的单元叫做granule.SGA组件,像数据缓冲区,共享池,大池,以Granule为单位占用或释放一定数目的SGA的内存.Oracle以完整的Granule为单位为各个组件分配SGA内存. 所有的Granule的信息存储在Granule表中.Oracle在Granule表中维护Granule的状态和类型.
Granule的尺寸由SGA区的大小决定,在大部分平台, 当全部SGA的大小小于 128M 时,单位Ganule的大小为4MB,当全部SGA的大小大于 128M 时,单位Granule的大小为16MB.单位Ganule的大小也于操作系统的平台相关,例如,在32位的Window NT的机器上,SGA大小大于 128M 时单位Granule的内存为8MB.
当前Granule的尺寸被记录在视图V$SGA_DYNAMIC_COMPONENTS中. 所有的动态SGA的组件使用Granule的单位是一样的.
如果你指定一个组件的尺寸不是单位Granule尺寸的倍数,那么Oracle会计算大于接近于当前尺寸的最接近的Granule的倍数. 例如,如果单位granule大小为4MB,并且你指定DB_CACHE_SIZE为10MB,实际上分配的尺寸为12MB.
|
Oracle 将各组件信息和他们的Granule 记录在记分板(scoreboard)中;每一个组件拥有自己的graunule,记分板包含已分配和未分配给组件的granule的数量,以及granules的目标尺寸,并按照granues的目标尺寸分配内存大小.分配granule操作的开始时间被记录到日志. Oracle每个组件都支持初始化granule的数量和最大的granule的数量.
每个修改granule数量的操作,Oracle都会记录该操作,目标尺寸,SGA组件调整记分板的开始时间.Oracle只有操作完成后猜更新过程记录.操作完成后,Oracle将当前的大小替换为目标尺寸并且清楚目标尺寸和过程记录. 操作结束时,数据库管理员可以看到改变了多少granule.Oracle按照改变后的实际尺寸更新SGA相应的初始化参数值.
Oracle循环记录最近100个对于记分板的操作.固定视图可以展示当前记分板的状态和最后操作记分板的100个操作.
数据库启动时,Oracle从初始化参数中读取各组件的granule数量,获得系统内存的现在,并且为SGA分配虚拟地址空间. 初始化参数SGA_MAX_SIZE标明实例SGA的最大尺寸.它的实际大小为不小于当前尺寸的Granule的整数倍.
数据库管理员可以通过ALTER SYSTEM 修改SGA组件的初始化参数. Oracle接受新的尺寸,并将向上调整为16MB内存的倍数,增加或减少ganule来满足目标尺寸.Oracle必须拥有足够的空闲granul才能满足请求.如果当前SGA内存的大小小于SGA_MAX_SIZE,Oracle能分配更多的granule直到达到SGA_MAX_SIZE.
|
数据高速缓存是SGA区的一部分,它保持了最近从数据库文件中读取的数据库的拷贝,所有连接的数据库实例的用户连接进程能共享数据高速缓存.
数据高速缓存和共享SQL缓存被逻辑的分成了多个区域.这种多区域的组织方式可以减少多处理器系统的竞争.
数据库高速缓存被分成了两个列表:写列表和最近最少使用列表(LRU).写列表包含脏数据,它包含了发生改变但是没有写到磁盘的数据. LRU 列表包含空闲缓冲区,常驻缓冲区和还没有转移到写列表的脏数据.空闲缓冲区不包含任何有用的数据. 常驻缓冲区是当前使用缓冲区域.
当Oracle进程访问缓冲区时,后台进程将刚刚访问的区域转移到最近最常使用(MRU)区域,即LRU列表的结尾. 随着越来越多的缓冲被转移到MRU,脏数据向LRU 结尾移动(dirty buffer age toward the LRU end of the LRU list).
当Oracle用户进程需要的数据时,它首先冲高速缓冲区搜索数据,如果用户进程在缓冲区内找到数据,这称为一次缓冲命中 (a cache hit), 它直接从内存读取数据.如果进程在高速缓冲区中不能找到自己所需的数据 ,这叫做一次缓冲丢失 (a cache miss), 它必须从数据文件拷贝数据数据高速缓冲区,然后再访问数据. 缓冲命中访问访问速度远远超过缓冲丢失命中访问速度.
在读数据到数据高速缓冲区前,数据库进程必须先找到空闲的缓冲块.这些进程搜索LRU列表, 直到进程搜索到空闲缓存块或者搜索到了列表的顶端.
如果用户进程在搜索LRU列表时查找到脏的数据缓冲块,就会将其转移到写列表,并且继续查找.当进程找到空闲缓冲块,就从磁盘将相应的数据库读取到内存中,并且将其转移到MRU列表,即LRU列表到结尾.
如果Oracle用户进程搜索到LRU列表的顶端都没能找到空闲缓冲块,用户进程会停止搜索LRU列表,并且标记DBW0后台进程将脏数据写到磁盘.
"Database Writer Process (DBWn)" for more information about DBWn processes |