Oracle 的内存由
系统全局区(System Global Area,简称 SGA)和
程序全局区(Program Global Area,简称 PGA)组成。
系统全局区(system global area,SGA)
SGA系统全局区是一组包含了 Oracle 数据库数据及实例控制信息的共享的内存结构。当多个用户并发地连接到同一个实例后,这些用户将共享此实例SGA 中的数据。因此 SGA 也被称为共享全局区(shared global area)。
SGA 越大系统的性能越好,但 SGA 过大也会起到反作用。一般情况下,SGA 不应超过系统实际内存的 1/2。但从 Oracle 9i 开始支持动态 SGA 特性,即无需关闭实例就可以改变数据高速缓冲区、共享池和大池的大小。数据高速缓冲区、共享池的大小也可以根据工负载自动调整,但 SGA 的总大小不能超过初始化参数 SGA_MAX_SIZE 的设置。。
SGA 的构成
如图1-1 所示,SGA 包括三个子缓冲区:保留缓冲区、循环缓冲区和非标准大小块缓冲区。SGA 包括以下结构:
● 数据高速缓冲区(Data Buffer Cache)
● 重做日志缓冲区(Redo Log Buffer)
● 共享池(Shared Pool)
● Java 池(Java Pool)
● 大池(Large Pool)
● 流池(Stream Pool)
一、数据库高速缓冲区(Database Buffer Cache)
在 Oracle 中无论是读取还是修改数据,都是由服务器进程在数据库高速缓冲区中完成的。数据库高速缓冲区的作用就是用来缓存最近从数据库中读出的数据块,并可供其他客户进程共享。用户进程查看数据时,首先检查需要的信息是否在缓冲区内,如果在缓冲区中,就可以直接访问,否则访问物理文件并读取数据块到数据库缓冲区。我们知道内存的读写速度要比物理设备的读写速度快很多,这样就可以大大提高 Oracle 数据库的性能。
1) 数据库高速缓冲区的子缓冲区
根据缓冲数据块的状态,Oracle 将数据高速缓冲区可划分成:
● 脏缓冲区(Dirty Buffer):
当数据库发生 DML(Insert、Update、Delete)操作时,会对缓冲区内容进行修改,这样缓冲区的内容就会和相对应的数据文件不一致,这时,缓冲区标识为“脏缓冲区”。
● 自由缓冲区(Free Buffer):
当“脏缓冲区”的内容被写入数据文件后,因为该缓冲区与相应数据文件部分内容一致,所以将这些缓冲区称为“自由缓冲区”。
当执行 SELECT 语句时,会将对应数据文件部分数据读取到数据高速缓存的相应缓冲区,因为缓冲区与数据块内容完全一致,所以这些缓冲区也被称为“自由缓冲区”。
● 忙缓冲区(Pinned Buffer):
“忙缓冲区”是指服务器进程正在访问的缓冲区。
每个数据库的数据库高速缓冲区大小有限,所以一般不会把磁盘上的所有数据都可以存放在缓冲区中。
为了防止数据库高速缓冲区空间不够用,Oracle 会将脏缓冲区中的数据写入对应的数据文件中,以腾出空间给新的数据。
如果缓冲区不脏,即为“自由缓冲区”,它可以直接被读入新的数据块。随后访问被写入磁盘导致额外的高速缓存未命中的数据。
“脏列表”的作用就是记录脏缓冲区的情况。如果某些缓冲区中的数据块被修改,就会加入该列表,只有脏列表中的缓冲区数据块需要写回数据库文件,一旦写回数据库文件,冲区就会从脏列表中清除。
2) 非标准块大小支持
数据库块是 Oracle 数据库 I/O 的最小单位。
每个数据库都可以通过参数 DB_BLOCK_SIZE 指定标准块大小(2k、4k、8k、16k32k),默认为 8k。但是 Oracle 数据库同时支持多种块大小,我们称这些标准块以外的块为“非标准大小块”。
非标准大小块的高速缓冲区大小指定以下参数(DB_nK_CACHE_SIZE):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_CACHE_SIZE 的值决定。
3) 使用多个缓冲区
数据库管理员(DBA )可以通过创建多个缓冲池来提高数据库缓冲区高速缓存的性能。
用户可以指定方案对象(schema object)(表,簇,索引,及分区)使用相应的缓冲池,以便控制数据被移出缓存区的时机。
● 保留缓冲区(Keep Buffer Cache):
用来保留在内存中最有可能重用的对象。保留这些对象将减少 I/O 操作,指定 DB_KEEP_CACHE_SIZE 参数的值配置。
● 循环缓冲区(Recycle Buffer Cache):
用来保留被重用机会不大的内存块。指定 DB_RECYCLE_CACHE_SIZE 参数的值配置该缓冲区的大小。
● 默认缓冲区(Default Buffer Cache):
此池始终存在。它相当于一个实例的数据库高速缓冲区中保留和循环区以外的部分。指定参数 DB_CACHE_SIZE。
注:保留缓冲区和循环缓冲区并非默认缓冲区的子集。
可以使用 BUFFER_POOL 子句对对象定义默认的缓冲区。
EXAMPLE:CREATE INDEX cust_idx …STORAGE (BUFFER_POOL KEEP);ALTER TABLE oe.customersSTORAGE (BUFFER_POOL RECYCLE);
4) 数据库高速缓冲区空间管理
Oracle 用 LRU(Least Recently Used)算法来管理数据高速缓冲区。该算法将最近用的数据块按照使用时间的早晚排成队列,当缓冲区占满后,调入新的数据块时,必须清除已有的数据块,来获得空闲数据块空间,那么,最合理的选择就是清除最早没有使用数据块,因为使用该块的概率相对比较小。通过规划 SGA 时合理地设置数据高速缓存的尺寸,尽量的避免缓冲区占满的情况发生,否则就会降低系统的效率。
Oracle 将队列分成两端,分别为热端和冷端。
假设新数据块 K 将要被读入,又没有空闲位置,则 Oracle 会对冷端头 J 块进行判断假设 J 被访问次数为 1,Oracle 将会认为 J 不是一个经常被访问的块(冷),则会将 块踢出队列,将 K 插入至 F 的位置,F 和其他块右移:
假设新数据块 L 将要被读入,又没有空闲位置,则 Oracle 会对冷端头 I 块进行判断假设 I 被访问次数为 5,Oracle 将会认为 I 是一个经常被访问的块(热),则会将 I 块入热端头,A 和其他快右移如下图所示:
这时,将对下一个冷端头块 H 进行判断:假设 H 被访问次数为 1,Oracle 将会认为 H 不是一个经常被访问的块(冷),则会将 H块踢出队列,将 L 插入至 E 的位置,E 和其他块右移:
但是这时,我们会发现。I 块被放入热端头,经过漫长的时间,I 块最终会被放到冷端头进行判断;如果这段时间中,即使 I 没有再被访问过,I 的访问次数也仍然是 5,这样 I将再次回到热端头,这样就造成了死循环,I 永远无法被踢出列表。
因此,当 I 被放到热端头的时候,访问次数将会被清零。如果这段时间 I 被访问多次,则有机会回到热端头,否则,可能被踢出列表。
5) 数据库高速缓冲区的大小管理
- 1> 连接数据库
[oracle@oracle ~ ]$ sqlplus / as sysdba
- 2> 显示数据库高速缓冲区的大小
SQL> show parameter db_cache_sizeNAME TYPE VALUE
------------------------------------ ----------- ------------------------------
db_cache_size big integer 0
- 3> 显示保留缓冲区的大小
SQL> show parameter db_keep_cache_sizeNAME TYPE VALUE
------------------------------------ ----------- ------------------------------ db_keep_cache_size big integer 0
- 4> 显示循环缓冲区的大小
SQL> show parameter db_recycle_cache_size
- 5> 修改数据库高速缓冲区的大小
SQL> ALTER SYSTEM SET db_cache_size=500m;
- 6> 清空数据库高速缓冲区
SQL> ALTER SYSTEM FLUSH buffer_cache;