Oracle 内存架构详解(一)

2014-11-24 18:18:35 · 作者: · 浏览: 0


Oracle内存存储的主要内容是什么:


程序代码(PLSQLJava);


关于已经连接的会话的信息,包括当前所有活动和非活动会话;


程序运行时必须的相关信息,例如查询计划;


Oracle进程之间共享的信息和相互交流的信息,例如锁;


那些被永久存储在外围存储介质上,被cache在内存中的数据(如redo log条目,数据块)。



每个Oracle数据库都是由Oracle Instance(实例)与数据库(数据文件,控制文件、重做日志文件)组成,其中所谓实例就是用户同数据库交互的媒介,用户通过于一个实例相连来操作数据库。而实例又是由统一的内存结构(SGAPGAUGA)和一批内存驻留进程组成。实例在操作系统中用ORACLE_SID来标识,在Oracle中用参数INSTANCE_NAME来标识, 它们两个的值是相同的。数据库启动时,系统首先在服务器内存中分配系统全局区(SGA), 构成了Oracle的内存结构,然后启动若干个常驻内存的操作系统进程,即组成了Oracle的 进程结构,内存区域和后台进程合称为一个Oracle实例。




一. SGA



SGA是一组为系统分配的共享的内存结构,可以包含一个数据库实例的数据或控制信息。如果多个用户连接到同一个数据库实例,在实例的SGA中,数据可以被多个用户共享。 当数据库实例启动时,SGA的内存被自动分配;当数据库实例关闭时,SGA内存被回收。 SGA是占用内存最大的一个区域,同时也是影响数据库性能的重要因素。



SGA区是可读写的。所有登录到实例的用户都能读取SGA中的信息,而在oracle做执行操作时,服务进程会将修改的信息写入SGA区。


SGA主要包括了以下的数据结构:


数据缓冲(Buffer Cache


重做日志缓冲(Redo Log Buffer


共享池(Shared Pool


Java池(Java Pool


大池(Large Pool


流池(Streams Pool --- 10g以后才有)


数据字典缓存(Data Dictionary Cache


其他信息(如数据库和实例的状态信息)



SQL> show sga



Total System Global Area 612368384 bytes


Fixed Size 1250428 bytes


Variable Size 192940932 bytes


Database Buffers 411041792 bytes


Redo Buffers 7135232 bytes



SGA 中的数据字典缓存其他信息 会被实例的后台进程所访问,它们在实例启动后就固定在SGA中了,而且不会改变,所以这部分又称为固定SGAFixed SGA)。这部分区域的大小一般小于100K



Shared PoolJava PoolLarge PoolStreams Pool这几块内存区的大小是相应系统参数设置而改变的,所以有通称为可变SGAVariable SGA)。







通过下面的语句查询


SQL> show parameter sga


NAME TYPE VALUE


------------------------------------ ----------- -------


lock_sga boolean FALSE


pre_page_sga boolean FALSE


sga_max_size big integer 584M


sga_target big integer 584M



先对这几个参数做一下说明:



SQL> select name,value ,ISSYS_MODIFIABLE from v$parameter where name like 'sga%';


NAME VALUE ISSYS_MOD


--------------- --------------- ---------


sga_max_size 612368384 FALSE


sga_target 612368384 IMMEDIATE



如果ISSYS_MODIFIABLE 返回的是false,说明该参数无法用alter system语句动态修改,需要重启数据库


所以sga_max_size 是不可以动态调整的。但是我们可以对sga_target 进行动态的调整。



SGA_MAX_SIZE


SGA区包括了各种缓冲区和内存池,而大部分都可以通过特定的参数来指定他们的大小。但是,作为一个昂贵的资源,一个系统的物理内存大小是有限。尽管对于CPU的内存寻址来说,是无需关系实际的物理内存大小的,但是过多的使用虚拟内存导致page in/out,会大大影响系统的性能,甚至可能会导致系统crash。所以需要有一个参数来控制SGA使用虚拟内存的最大大小,这个参数就是SGA_MAX_SIZE


当实例启动后,各个内存区只分配实例所需要的最小大小,在随后的运行过程中,再根据需要扩展他们的大小,而他们的总和大小受到了SGA_MAX_SIZE的限制。


当试图增加一个内存的大小,并且如果这个值导致所有内存区大小总和大于SGA_MAX_SIZE时,oracle会提示错误,不允许修改。


当然,如果在设置参数时,指定区域为spfile时(包括修改SGA_MAX_SIZE本身),是不会受到这个限制的。这样就可能出现这样的情况,在spfile中,SGA各个内存区设置大小总和大于SGA_MAX_SIZE。这时,oracle会如下处理:当实例再次启动时,如果发现SGA各个内存总和大于SGA_MAX_SIZE,它会将SGA_MAX_SIZE的值修改为SGA各个内存区总和的值。


SGA所分配的是虚拟内存,但是,在我们配置SGA时,一定要使整个SGA区都在物理内存中,否则,会导致SGA频繁的页入/页出,会极大影响系统性能。


对于OLTP系统,一般的建议是将SGA_MAX_SIZE 设为物理内存的60%PGA 设为20%。 但是现在服务器内存是相当大的。 几百G的内存随处可见。60%也就是几百G内存。 显然这样也是不合适的。 所以要根据自己系统来设定设定这个值。这个也就所说的DBA的经验。 这是是需要经验的积累。



下表的几个数值供参考。




SGA的实际大小可以通过以下公式估算:


SGA实际大小 = DB_CACHE_SIZE + DB_KEEP_CACHE_SIZE + DB_RECYCLE_CACHE_SIZE + DB_nk_CACHE_SIZE + SHARED_POOL_SIZE + LARGE_POOL_SIZE + JAVA_POOL_SIZE + STREAMS_POOL_SIZE10g中的新内存池) + LOG_BUFFERS+11K(Redo Log Buffer的保护页) + 1MB + 16M(SGA内部内存消耗,适合于9i及之前