【深入解析--eygle】学习笔记
1.3 SGA管理
SGA指系统全局区(System Global Area),是一块用于加载数据、对象并保存运行状态和数据库控制信息的一块内存区域,在数据库实例启动时分配,当实例关闭时释放,每个实例都拥有自己的SGA区。
在第一章曾经?到,当数据库启动到nomount状态时,SGA已经分配,同时启动后台进程,在SQL*Plus中通过show sga命令可以看到SGA的分配情况:?
sys@felix SQL>show parameter sga
NAME TYPE VALUE
---------------------------------------------------------- ------------------------------
lock_sga boolean FALSE
pre_page_sga boolean FALSE
sga_max_size big integer 400M
sga_target big integer 0
16:12:56 sys@felix SQL>
连接到Oracle数据库的用户都可以共享SGA中的数据,通常为了更优化的性能,我们总是期望在物理内存允许的情况下,设置更高的SGA区,以减少物理I/O(SGA中数据缓冲区的增大可以有效地减少物理读)。
1.4 SGA
下图是最常见的数据库实例体系结构图,展现了SGA的结构:

![\]()
![\]()
?
1.4.1 固定区域 - Fixed Area
Fixed Size 部分是SGA中的固定部分,包含几千个变量和一些小的数据结构,如Latch或地址指针等,这部分内存分配和特定的数据库版本以及平台有关,不受用户控制,而且这些信息对于数据库来说非常重要,但是通常我们用户不需要关心。
固定部分只需要很小的内存,可以通过一个内部表X$KSMFSV([K]ernel [S]ervice Layer , [M]emoryManagement,Addresses of [F]ixed [S]GA [V]ariables)查询。此外Oracle的内部表X$KSMMEM记录了整个SGA的地址映射关系,通过X$KSMFSV和X$KSMMEM关联,可以找出Fixed Area中每个变量的设置。
在32位平台上,X$KSMMEM表中每条记录代表4 Bytes,在64位平台,每条记录代表4 Bytes:
sys@felix SQL>select * from x$ksmmem whererownum <5;
ADDR INDX INST_ID KSMMMVAL
---------------- ---------- --------------------------
0000000060000000 0 1 00
0000000060000008 1 1 00
0000000060000010 2 1 00
0000000060000018 3 1 00
16:21:39 sys@felix SQL>
sys@felix SQL>select ksmfsnam,ksmfssiz from x$ksmfsv where ksmfsnam='kcsgscn_';
KSMFSNAM KSMFSSIZ
----------------- --------
kcsgscn_ 48
16:23:51 sys@felix SQL>
通过ORADEBUG工具可以得到当前内存中的SCN值:
16:23:51 sys@felix SQL>oradebug setmypid
Statement processed.
16:26:19 sys@felix SQL>oradebug DUMPvar SGA kcsgscn_
kcslf kcsgscn_ [060019598, 0600195C8) = 00183004 00000000 00000000 00000000 000024AE 00000000 00000000 00000000 00000000 00000000 60019278 00000000
16:26:22 sys@felix SQL>?
SCN值获取如下:
sys@felix SQL>selectto_number('183004','xxxxxxxxxx') from dual;
TO_NUMBER('183004','XXXXXXXXXX')
--------------------------------
1585156
16:27:05 sys@felix SQL>
Fixed Area包含很多控制信息,但是需要注意的是,查询X$KSMFSV视图可能会导致进程异常,需要谨慎使用
1.4.1.1 Buffer Cache
Buffer Cache-缓冲区高速缓存,用于存储最近使用的数据块,这些数据块可能是被修改过的,也可能是未经修改的。我们知道,在Oracle对数据的处理过程中,代价最昂贵的就是物理I/O(Physical I/O)操作了,同样的数据从内存中得到要比从磁盘上读取快得多,所以将尽可能多的数据保存在内存中,可以减少磁盘I/O操作,从而提高数据库的性能。
从Oracle9i开始,Oracle引入了一个新的初始化参数db_cache_size ,该参数用来定义主Block Size(db_block_size定义的块大小)的Default缓冲池的大小
各内存组件所使用的Granule大小可以通过动态性能视图来查询:
16:36:00 sys@felix SQL>select component,granule_size from v$sga_dynamic_components;
COMPONENT GRANULE_SIZE
--------------------------------- ------------
shared pool 4194304
large pool 4194304
java pool 4194304
streams pool 4194304
DEFAULT buffer cache 4194304
KEEP buffer cache 4194304
RECYCLE buffer cache 4194304
DEFAULT 2K buffer cache 4194304
DEFAULT 4K buffer cache 4194304
DEFAULT 8K buffer cache 4194304
DEFAULT 16K buffer cache 4194304
DEFAULT 32K buffer cache 4194304
Shared IO Pool 4194304
ASM Buffer Cache 4194304
14 rows selected.
17:33:14 sys@felix SQL>
Oracle管理Buffer Cache使用的是LRU算法,但是这又带来另外一个问题,很多批处理的操作(比如全表扫?等)可能会导致Buffer Cache的刷新,将经常使用的数据“挤出”Buffer Cache,在不同版本中,Oracle不停的改进LRU算法,以避免这类操作的过度影响。
但是在此之外,Oracle提供了BufferCache的多缓冲池技术从另外一个方面来解决这个问题。所谓的多缓冲池技术是指,根据不同数据的不同访问方式,将Buffer Cache分为Default、Keep和Recycle池三个部分。对于经常使用的数据,我们可以在建表时就指定将其存放在Keep池中;对于经常一次性读取使用的数据,可以将其存放在Recycle池中;Keep池中的数据倾向于一直保存,Recycle池中的数据倾向于即时老化,而Default池则存放未指定存储池的数据,按照LRU算法管理。
默认情况下,所有表都使用DEF