Oracle 内存结构
与 Oracle 实例关联的基本内存结构包括:
系统全局区 (SGA):由所有服务器和后台进程共享。SGA 中存储的数据示例包括高速缓存的数据块和共享 SQL 区域。
程序全局区 (PGA):各个服务器进程和后台进程专用,每个进程都有一个 PGA。
SGA 是共享内存区,包含实例的数据和控制信息,由以下各项组成:
数据库缓冲区高速缓存:用于缓存从磁盘检索到的数据块
重做日志缓冲区:用于缓存重做信息,直到其可以写入磁盘为止
共享池:用于缓存可在用户间共享的各种结构
大型池:用于缓冲大型 I/O 请求的可选区域,以便支持并行查询、共享服务器、Oracle XA 以及某些类型的备份操作
Java 池:用于存放 Java 虚拟机 (JVM) 中特定于会话的 Java 代码和数据
流池:由 Oracle Streams 使用
保留缓冲区高速缓存:用于存放会尽可能长地保留在缓冲区高速缓存中的数据
循环缓冲区高速缓存:用于存放缓冲区高速缓存中很快过期的数据
nK 块大小缓冲区高速缓存:用于缓存大小与默认数据库块大小不同的数据块,用来支持可传输的表空间
数据库缓冲区高速缓存、共享池、大型池、流池和 Java 池的大小可以按照当前需求自动调整。而且,这些内存缓冲区以及保留缓冲区高速缓存、循环缓冲区高速缓存和 nK 块大小缓冲区高速缓存可以在不关闭实例的情况下进行更改。
Oracle 数据库会提供预警和指导,以标识内存大小问题,从而帮助确定相应的内存参数值。
程序全局区 (PGA) 是一个内存区,其中包含每个服务器进程的数据及控制信息。服务器进程是处理客户机请求的进程。每个服务器进程都有在服务器进程启动时创建的自己专用的 PGA。只有该服务器进程才能访问。
所用 PGA 内存量和 PGA 的内容取决于实例是否是在共享服务器模式下配置的。通常,PGA 包含下列内容:
专用 SQL 区:包含绑定信息和运行时内存结构等数据。发出 SQL 语句的每个会话都有一个专用 SQL 区。
会话内存:此处分配的内存用于存放会话变量以及与该会话相关的其它信息。
1.缓冲区高速缓存 data buffer cache
通过指定 DB_CACHE_SIZE 参数的值,可以配置缓冲区高速缓存。缓冲区高速缓存可存放数据文件中块大小为 DB_BLOCK_SIZE 的数据块的副本。缓冲区高速缓存是 SGA 的一部分;因此所有用户都可以共享这些块。服务器进程将数据文件中的数据读入缓冲区高速缓存。为了提高性能,服务器进程有时在一个读操作中会读取多个块。然后由 DBWn 进程将数据从缓冲区高速缓存写入数据文件。为提高性能,DBWn 在一个写操作中会写入多个块。
在任何给定时间,缓冲区高速缓存都可能会存放一个数据库块的多个副本。虽然该块只存在一个当前副本,但为了满足查询需要,服务器进程可能需要根据过去的映像信息构造读一致性副本。这称为读一致性 (CR) 块。
最近最少使用 (LRU) 列表可反映缓冲区的使用情况。缓冲区将依据其被引用时间的远近和引用频率进行排序。因此,最经常使用且最近使用过的缓冲区将列在最近最常使用一端。传入的块先被复制到最近最少使用一端的缓冲区中,然后该缓冲区将被指定到列表中央,作为起点。从这个起点开始,缓冲区根据使用情况在列表中上下移动。
缓冲区高速缓存中的缓冲区可以处于以下四种状态之一:
已连接:当前正将该块读入高速缓存或正在写入该块。其它会话正等待访问该块。
干净的:该缓冲区目前未连接,如果其当前内容(数据块)将不再被引用,则可以立即执行过期处理。这些内容与磁盘保持同步,或者缓冲区包含块的读一致性快照。
空闲/未使用:缓冲区因实例刚启动而处于空白状态。此状态与“干净的”状态非常相似,不同之处在于缓冲区未曾使用过。
灰:缓冲区不再处于连接状态,但内容(数据块)已更改,因此必须先通过 DBWn 将内容刷新到磁盘,然后才能执行过期处理。
服务器进程使用缓冲区高速缓存中的缓冲区;而 DBWn 进程通过将更改的缓冲区写回数据文件,使高速缓存中的缓冲区变为可用状态。检查点队列中列出将要写出到磁盘的缓冲区。
Oracle 数据库支持同一数据库中有多种块大小。标准块大小用于 SYSTEM 表空间。标准块大小可以通过设置初始化参数 DB_BLOCK_SIZE 来指定。其有效值介于 2 KB 到 32 KB 之间,默认值为 8 KB。非标准块大小的缓冲区的高速缓存大小通过以下参数指定:
DB_2K_CACHE_SIZE
DB_4K_CACHE_SIZE
DB_8K_CACHE_SIZE
DB_16K_CACHE_SIZE
DB_32K_CACHE_SIZE
DB_nK_CACHE_SIZE 参数不能用于调整标准块大小的高速缓存的大小。如果 DB_BLOCK_SIZE 的值为 nK,则设置 DB_nK_CACHE_SIZE 是非法的。标准块大小的高速缓存的大小始终由 DB_CACHE_SIZE 的值确定。
由于每个缓冲区高速缓存的大小都有限制,因此,通常并非磁盘上的所有数据都能放在高速缓存中。当高速缓存写满时,后续高速缓存未命中会导致 Oracle 数据库将高速缓存中已有的灰数据写入磁盘,以便为新数据腾出空间。(如果缓冲区中没有灰数据,则不需要写入磁盘即可将新块读入该缓冲区。)以后若对已写入磁盘的任何数据进行访问,则会导致再次出现高速缓存未命中现象。
数据请求导致高速缓存命中的几率会受到高速缓存大小的影响。高速缓存越大,包含所请求数据的几率也就越大。因此,增加高速缓存大小会提高引起高速缓存命中的数据请求的百分比。
数据库管理员 (DBA) 可以创建多个缓冲区池来提高数据库缓冲区高速缓存的性能。您可以根据对象的访问情况将其分配给某个缓冲区池。缓冲区池有三种:
保留:此池用于保留内存中可能要重用的对象。将这些对象保留在内存中可减少 I/O 操作。通过使池的大小大于分配给该池的各个段的总大小,可以将缓冲区保留在此池中。这意味着缓冲区不必执行过期处理。保留池可通过指定 DB_KEEP_CACHE_SIZE 参数的值来配置。
循环:此池用于内存中重用几率很小的块。循环池的大小要小于分配给该池的各个段的总大小。这意味着读入该池的块经常需要在缓冲区内执行过期处理。循环池可通过指定 DB_RECYCLE_CACHE_SIZE 参数的值来配置。
默认:此池始终存在。它相当于没有保留池和循环池的实例的缓冲区高速缓存,可通过 DB_CACHE_SIZE 参数进行配置。
注:保留池或循环池中的内存不是默认缓冲区池的子集。
CREATE INDEX cust_idx …
STORAGE (BUFFER_POOL KEEP …);
ALTER TABLE oe.customers
STORAGE (BUFFER_POOL RECYCLE);
ALTER INDEX oe.cust_lname_ix
STORAGE (BUFFER_POOL KEEP);
手工刷新内存:
alter system flush buffer cache;
BUFFER_POOL 子句用于定义对象的默认缓冲区池。它是 STORAGE 子句的一部分,对 CREATE 和 ALTER 表、簇和索引语句有效。未明确设置缓冲区池的对象中的块将进入默认缓冲区池。
语法为:BUFFER_POOL [KEEP | RECYCLE | DEFAULT]。
使用 ALTER 语句更改对象的默认缓冲区池时,已缓存的块会一直保留在其当前缓冲区中,直到正常缓冲区管理活动将它们清除为止。从磁盘读取的块将被放置在为该段新指定的缓冲区池中。
由于多个缓冲区池被分配给某一个段,所以有多个段的对象可以将块放置在多个缓冲区池中。例如,按索引组织的表在索引段和溢出段上可以有多个不同的池。
2.共享池 shared pool
大小通过 SHARED_POOL_SIZE 指定。
库高速缓存包含语句文本、已进行语法分析的代码和执行计划。
数据字典高速缓存包含数据字典表中各表、列和权限的定义。
用户全局区 (UGA) 包含会话信息(如果使用 Oracle 共享服务器)。
库高速缓存:库高速缓存包含共享 SQL 区和 PL/SQL 区 - 经过完全语法分析或编译的 PL/SQL 块和 SQL 语句的表示法。PL/SQL 块包括:
过程和函数
程序包
触发器
匿名
PL/SQL 块
数据字典高速缓存:数据字典高速缓存将字典对象的定义存放在内存中。
结果高速缓存:结果高速缓存包含 SQL 查询结果高速缓存和 PL/SQL 函数结果高速缓存。此高速缓存用于存储 SQL 查询或 PL/SQL 函数的结果,以加快其将来的执行速度。
用户全局区:UGA 包含 Oracle 共享服务器的会话信息。使用共享服务器会话时,如果尚未配置大型池,则 UGA 位于共享池中。
3.大型池large pool
可配置为 SGA 中一个单独的内存区
大小由 LARGE_POOL_SIZE 参数指定
用于在内存中为以下各项存储数据:
--UGA
--备份和还原操作
--并行查询消息传送
大型池必须显式配置。大型池的内存不是来自共享池,而是直接来自 SGA,这就增大了 Oracle 服务器在实例启动时需要的共享内存量。
大型池用于为以下各项分配大量会话内存:
--I/O 服务器进程
--备份和还原操作
--Oracle 共享服务器进程和 Oracle XA 接口(事务处理与多个数据库交互时使用)
由于从大型池为 Oracle 共享服务器分配会话内存,因此共享池中由于频繁分配和取消分配大对象而产生的碎片也就很少。将大对象从共享池中分离出来,可增加共享池内存的使用效率,这意味着,它可以将更多内存用于处理新的请求,以及在需要时用于保留现有数据。
4.Java pool
可配置为 SGA 中一个单独的内存区
大小由 JAVA_POOL_SIZE 参数指定
用于将 JVM 中特定于会话的所有 Java 代码和数据存储在内存中
5.重做日志缓冲区 redo buffer cache
Oracle 服务器进程将重做条目从用户的内存空间复制到每个 DML 或 DDL 语句的重做日志缓冲区。重做条目包含重建或重做 DML 和 DDL 操作对数据库的更改所必需的信息。它们用于数据库恢复,需要占用缓冲区中的连续空间。
重做日志缓冲区是一个循环缓冲区;服务器进程可以用新条目覆盖重做日志缓冲区中已写入磁盘的条目。LGWR 进程的写速度通常都很快,足以确保缓冲区中始终有存储新条目的空间。LGWR 进程将重做日志缓冲区写入磁盘上的活动联机重做日志文件(或活动组成员)中。LGWR 进程将 LGWR 上次写入磁盘以来进入缓冲区的所有重做条目复制到磁盘。
什么导致 LGWR 执行写操作?
用户进程提交事务处理时
每隔三秒,或每当重做日志缓冲区占满三分之一时
DBWn 进程将修改的缓冲区写入磁盘时(如果相应的重做日志数据尚未写入磁盘)