oracle 内存分配和调优 总结

oracle 内存分配和调优 总结
http://blog.itpub.net/12272958/viewspace-696834/
http://lqding.blog.51cto.com/9123978/1693659


        一、概述:                  

oracle 的内存可以按照共享和私有的角度分为系统全局区和进程全局区,也就是 SGA和 PGA(process global area or private global area)。对于 SGA 区域内的内存来说,是共享的全局的,在 UNIX 上,必须为 oracle 设置共享内存段(可以是一个或者多个),因为 oracle 在UNIX 上是多进程;而在 WINDOWS 上 oracle 是单进程(多个线程),所以不用设置共享内存段。PGA 是属于进程(线程)私有的区域。在 oracle 使用共享服务器模式下(MTS),PGA中的一部分,也就是 UGA 会被放入共享内存 large_pool_size 中。

       发张图oracle内存架构组成,按照图上面的显示可以一目了然关键的参数和参数名称:

       

对于 SGA 部分,我们通过 sqlplus 中查询可以看到:
SQL> select * from v$sga; 
NAME                VALUE 
----------             --------------------
Fixed Size                   454032 
Variable Size             109051904 
Database Buffers             385875968 
Redo Buffers                667648 
Fixed Size:         
oracle 的不同平台和不同版本下可能不一样,但对于确定环境是一个固定的值,里面存储了 SGA 各部分组件的信息,可以看作引导建立 SGA 的区域。

Variable Size :        
包含了 shared_pool_size、java_pool_size、large_pool_size 等内存设置

Database Buffers :       
指数 据缓 冲区:         
在 8i 中包 含 db_block_buffer*db_block_size、buffer_pool_keep、buffer_pool_recycle 三 部 分内 存 。         
在 9i 中 包 含 db_cache_size 、db_keep_cache_size、db_recycle_cache_size、db_nk_cache_size。

Redo Buffers :        
指日志缓冲区,log_buffer。

在这里要额外说明一点的是,对于 v$parameter、v$sgastat、v$sga 查询值可能不一样。v$parameter 里面的值,是指用户在初
始化参数文件里面设置的值,v$sgastat 是 oracle 实际分配的日志缓冲区大小(因为缓冲区的分配值实际上是离散的,也不是以 block 为最小单位进行分配的),
v$sga 里面查询的值,是在 oracle 分配了日志缓冲区后,为了保护日志缓冲区,设置了一些保护页,通常我们会发现保护页大小大约是 11k(不同环境可能不一样)。       


二、SGA内参数及设置:              

2.1  Log_buffer 

对于日志缓冲区的大小设置,通常我觉得没有过多的建议,因为参考 LGWR 写的触发条件之后,我们会发现通常超过 3M 意义不是很大。作为一个正式系统,可能考虑先设置这部分为 log_buffer=3—5M  大小,然后针对具体情况再调整。

log_buffer是Redo log的buffer。
因此在这里必须要了解Redo Log的触发事件(LGWR)
1、当redo log buffer的容量达到1/3
2、设定的写redo log时间间隔到达,一般为3秒钟。
3、redo log buffer中重做日志容量到达1M
4、在DBWn将缓冲区中的数据写入到数据文件之前
5、每一次commit--提交事务。
上面的结论可以换句话说
1、log_buffer中的内容满1/3,缓存刷新一次。
2、最长间隔3秒钟,缓存刷新一次
3、log_buffer中的数据到达1M,缓存刷新一次。
4、每次提交一个“事务”,缓存刷新一次

2.2 Large_pool_size 

对于大缓冲池的设置,假如不使用 MTS(共享服务器),建议在 20—30M  足够了。这部分主要用来保存并行查询时候的一些信息,还有就是 RMAN 在备份的时候可能会使用到。如果设置了MTS,则由于 UGA 部分要移入这里,则需要具体根据 server process 数量和相关会话内存参数的设置来综合考虑这部分大小的设置。

2.3  Java_pool_size 

假如数据库没有使用 JAVA,我们通常认为保留 10—20M 大小足够。事实上可以更少,甚至最少只需要 32k,但具体跟安装数据库的时候的组件相关(比如 http server)。

2.4  Shared_pool_size

Shared_pool_size的开销通常应该维持在300M 以内。除非系统使用了大量的存储过程、函数、包,比如 oracle erp 这样的应用,可能会达到 500M 甚至更高。于是我们假定一个 1G 内存的系统,可能考虑设置该参数为 100M,2G 的系统考虑设置为 150M,8G 的系统可以考虑设置为 200—300M

2.5SGA_MAX_SIZE

SGA区包括了各种缓冲区和内存池,而大部分都可以通过特定的参数来指定他们的大小。但是,作为一个昂贵的资源,一个系统的物理内存大小是有限。尽管对于CPU的内存寻址来说,是无需关系实际的物理内存大小的(关于这一点,后面会做详细的介绍),但是过多的使用虚拟内存导致page in/out,会大大影响系统的性能,甚至可能会导致系统crash。所以需要有一个参数来控制SGA使用虚拟内存的最大大小,这个参数就是SGA_MAX_SIZE。当实例启动后,各个内存区只分配实例所需要的最小大小,在随后的运行过程中,再根据需要扩展他们的大小,而他们的总和大小受到了SGA_MAX_SIZE的限制。

对于OLTP系统,参考:

系统内存

SGA_MAX_SIZE值

1G

400-500M

2G

1G

4G

2500M

8G

5G



2.6 PRE_PAGE_SGA

oracle实例启动时,会只载入各个内存区最小的大小。而其他SGA内存只作为虚拟内存分配,
只有当进程touch到相应的页时,才会置换到物理内存中。但我们也许希望实例一启动后,所有SGA
都分配到物理内存。这时就可以通过设置PRE_PAGE_SGA参数来达到目的了。这个参数的默认值
为FALSE,即不将全部SGA置入物理内存中。当设置为TRUE时,实例启动会将全部SGA置入物理
内存中。它可以使实例启动达到它的最大性能状态,但是,启动时间也会更长(因为为了使所有SGA
都置入物理内存中,oracle进程需要touch所有的SGA页)。

2.7 LOCK_SGA

为了保证SGA都被锁定在物理内存中,而不必页入/页出,可以通过参数LOCK_SGA来控制。
这个参数默认值为FALSE,当指定为TRUE时,可以将全部SGA都锁定在物理内存中。当然,
有些系统不支持内存锁定,这个参数也就无效了。
2.8 SGA_TARGET

这里要介绍的时Oracle10g中引入的一个非常重要的参数。在10g之前,SGA的各个内存区
的大小都需要通过各自的参数指定,并且都无法超过参数指定大小的值,尽管他们之和可能并
没有达到SGA的最大限制。此外,一旦分配后,各个区的内存只能给本区使用,相互之间是不能共享的。
拿SGA中两个最重要的内存区Buffer Cache和Shared Pool来说,它们两个对实例的性能影响最大,
但是就有这样的矛盾存在:在内存资源有限的情况下,某些时候数据被cache的需求非常大,
为了提高buffer hit,就需要增加Buffer Cache,但由于SGA有限,只能从其他区“抢”过来——如缩小Shared Pool,
增加Buffer Cache;而有时又有大块的PLSQL代码被解析驻入内存中,导致Shared Pool不足,
甚至出现4031错误,又需要扩大Shared Pool,这时可能又需要人为干预,从Buffer Cache中将内存夺回来。

        有了这个新的特性后,SGA中的这种内存矛盾就迎刃而解了。这一特性被称为自动共享内存管理
(Automatic Shared Memory Management ASMM)。而控制这一特性的,也就仅仅是这一个参数SGA_TARGE。
设置这个参数后,你就不需要为每个内存区来指定大小了。SGA_TARGET指定了SGA可以使用的最大内存大小,
而SGA中各个内存的大小由Oracle自行控制,不需要人为指定。Oracle可以随时调节各个区域的大小,使之达到系
统性能最佳状态的个最合理大小,并且控制他们之和在SGA_TARGET指定的值之内。一旦给SGA_TARGET指定值后
(默认为0,即没有启动ASMM),就自动启动了ASMM特性。


三、oracle 内存调优办法

当项目的生产环境出现性能问题,我们如何通过判断那些参数需要调整呢?

3.1 检查ORACLE实例的Library Cache命中率:

标准:一般是大于99%

检查方式: select 1-(sum(reloads)/sum(pins)) "Library cache Hit Ratio" from v$librarycache;

处理措施:
如果Library cache Hit Ratio的值低于99%,应调高shared_pool_size的大小。通过sqlplus连接数据库执行如下命令,调整shared_pool_size的大小:
SQL>alter system flush shared_pool;
SQL>alter system set shared_pool_size=设定值 scope=spfile;

3.2 检查ORACLE实例的Data Buffer(数据缓冲区)命中率:

标准:一般是大于90%

检查方式:
    select 1 - (phy.value / (cur.value + con.value)) "HIT RATIO"
    from v$sysstat cur, v$sysstat con, v$sysstat phy
    where cur.name = 'db block gets'
    and con.name = 'consistent gets'
     and phy.name = 'physical reads';

处理措施:
如果HIT RATIO的值低于90%,应调高db_cache_size的大小。通过sqlplus连接数据库执行如下命令,
调整db_cache_size的大小
SQL>alter system set db_cache_size=设定值 scope=spfile
3.3 检查ORACLE实例的Dictionary Cache命中率:

标准:一般是大于95%

检查方式:
select 1 - (sum(getmisses) / sum(gets)) "Data Dictionary Hit Ratio"  from v$rowcache;

处理措施:
如果Data Dictionary Hit Ratio的值低于95%,应调高shared_pool_size的大小。通过sqlplus连接数据库执行如下命令,调整shared_pool_size的大小:
SQL>alter system flush shared_pool;
SQL>alter system set shared_pool_size=设定值 scope=spfile;

3.4  检查ORACLE实例的Log Buffer命中率:

标准:一般是小于1%

检查方式:
    select (req.value * 5000) / entries.value "Ratio"
      from v$sysstat req, v$sysstat entries
     where req.name = 'redo log space requests'
      and entries.name = 'redo entries';

处理措施:
如果Ratio高于1%,应调高log_buffer的大小。通过sqlplus连接数据库执行如下命令,调整log_buffer的大小:
SQL>alter system set log_buffer=设定值 scope=spfile;

3.5 检查undo_retention:

标准:undo_retention 的值必须大于max(maxquerylen)的值

检查方式:
col undo_retention format a30
select value "undo_retention" from v$parameter where name='undo_retention';
select max(maxquerylen) From v$undostat Where begin_time>sysdate-(1/4);

处理措施:
如果不满足要求,需要调高undo_retention 的值。通过sqlplus 连接数据库执行如下命
令,调整undo_retention 的大小:
SQL>alter system set undo_retention= 设定值 scope=spfile;

注:
32bit  和 64bit  的问题
对于 oracle 来说,存在着 32bit 与 64bit 的问题。这个问题影响到的主要是 SGA 的大小。在 32bit 的数据库下,通常 oracle 只能使用不超过 1.7G 的内存,即使我们拥有 12G 的内存,但是我们却只能使用 1.7G,这是一个莫大的遗憾。假如我们安装 64bit 的数据库,我们就可以使用很大的内存,我们几乎不可能达到上限。但是 64bit 的数据库必须安装在 64bit 的操作系统上,可惜目前 windows 上只能安装 32bit 的数据库. 但是在特定的操作系统下,可能提供了一定的手段,使得我们可以使用超过 1.7G 的内存,达到 2G 以上甚至更多。

=================补充=======================
Oracle数据库包含了如下基本内存组件
  • System global area (SGA)

    The SGA is a group of shared memory structures, known as SGA components, that contain data and control information for one Oracle Database instance. The SGA is shared by all server and background processes. Examples of data stored in the SGA include cached data blocks and shared SQL areas.

  • Program global area (PGA)

    A PGA is a nonshared memory region that contains data and control information exclusively for use by an Oracle process. The PGA is created by Oracle Database when an Oracle process is started.

    One PGA exists for each server process and background process. The collection of individual PGAs is the total instance PGA, or instance PGA. Database initialization parameters set the size of the instance PGA, not individual PGAs.

  • User Global Area (UGA)

    The UGA is memory associated with a user session.

  • Software code areas

    Software code areas are portions of memory used to store code that is being run or can be run. Oracle Database code is stored in a software area that is typically at a different location from user programs—a more exclusive or protected location.

wKiom1XxfF3gwmXiAAB_B9TkDdE975.gif


内存管理

Oracle依赖于内存相关的初始化参数来控制内存的管理。

内存管理有如下三个选项

  • Automatic memory management

    You specify the target size for instance memory. The database instance automatically tunes to the target memory size, redistributing memory as needed between the SGA and the instance PGA.

  • Automatic shared memory management

    This management mode is partially automated. You set a target size for the SGA and then have the option of setting an aggregate target size for the PGA or managing PGA work areas individually.

  • Manual memory management

    Instead of setting the total memory size, you set many initialization parameters to manage components of the SGA and instance PGA individually.

UGA概览

UGA是会话内存,用来保存会话变量例如登录信息,已经数据库会话需要的其他信息。

wKiom1XxgDjgo1icAAAJ-I2R6yE454.gif

当PL/SQL包加载进内存时,UGA中包含了package state,也就是调用PL/SQL时指定的变量值。

PGA概览

wKioL1XxiomDbCHzAAAyzJTwK_8991.gif

PGA缓冲区,则主要是为了某个用户进程所服务的。这个内存区不是共享的,只有这个用户的服务进程本身才能够访问它自己的PGA区。做个形象的比喻,SGA就好像是操作系统上的一个共享文件夹,不同用户可以以此为平台进行数据方面的交流。而PGA就好像是操作系统上的一个私有文件夹,只有这个文件夹的所有者才能够进行访问,其他用户都不能够访问。虽然程序缓存区不向其他用户的进程开放,但是这个内存区仍然肩负着一些重要的使命,如数据排序、权限控制等等都离不开这个内存区。

PGA组件

wKiom1XxiWLCAoCPAAAvRw_DT2E002.gif


私有SQL区包含了绑定变量值和运行时期内存结构信息等数据。每一个运行SQL语句的会话都有一个块私有SQL区。一个游标的私有SQL区又分为两个生命周期不同的区:

永久区,包含绑定变量信息。当游标关闭时被释放。

 运行区,当执行结束时释放。

Cursor 

wKioL1Xxjqrg1iAEAAAZPPRUSL8229.gif


cursor is a name or handle to a specific private SQL area

SGA包含如下组件

  • Database Buffer Cache

  • Redo Log Buffer

  • Shared Pool

  • Large Pool

  • Java Pool

  • Streams Pool

  • Fixed SGA

Buffer cache

wKioL1XxkYyh_lAEAAAjsVEZZCE233.gif

Buffer Cache是SGA区中专门用于存放从数据文件中读取的的数据块拷贝的区域。Oracle进程如果发现需要访问的数据块已经在buffer cache中,就直接读写内存中的相应区域,而无需读取数据文件,从而大大提高性能。Buffer cache对于所有oracle进程都是共享的,即能被所有oracle进程访问。

Buffer的大小和数据块一样。

Buffer cache按照类型分为3个池

  • Default pool

    This pool is the location where blocks are normally cached. Unless you manually configure separate pools, the default pool is the only buffer pool.

  • Keep pool

    This pool is intended for blocks that were accessed frequently, but which aged out of the default pool because of lack of space. The goal of the keep buffer pool is to retain objects in memory, thus avoiding I/O operations.

  • Recycle pool

    This pool is intended for blocks that are used infrequently. A recycle pool prevent objects from consuming unnecessary space in the cache.

Oracle还提供了非标准块大小的buffer cache。如果你建立的表空间指定的块大小为非数据库块大小,那么将使用这些buffer cache来缓存数据块。


wKiom1XyOjSCNl07AAEPMFWdt2c070.jpg

首先Oracle 以每个数据块的文件号、块号、类型做hash运算,得到hash值。

对于hash值相同的块,放在一个Hash Bucket中。

因为buffer的大小毕竟有限,buffer中的数据块需要根据一定的规则提出内存。

Oracle采用了LRU算法维护一个LRU链表,来决定哪些数据块被淘汰。

通用的淘汰算法如下

wKiom1XyO2Ly1SWzAALA0-v_iQE044.jpg

Oracle改进了LRU算法,引入了Touch count概念、以及LRU链表分为热端头和冷端头。

Touch count:

 用来记录数据块访问的频繁度,此数值在内存中不受保护,多个进程可以同时修改它。这个值并不是精准的表示块被访问的次数,只是一种趋势。3秒内无论多少用户,访问多少次块。此值加1.


wKiom1XyPTXDFE5WAACyWyTZBVc922.jpg

当数据块第一次被放到buffer中,Oracle将其放置在冷端的头部。

如果buffer已经没有空闲空间,那么如何淘汰数据块呢?Oracle从LRU的冷端尾部扫描数据块,当发现数据块的Touch count大于等于2时,将数据块移动到热端头部,并将Touch count置为0 。当Oracle发现Touch count小于2时,则淘汰该数据块。


当数据块被修改了,我们把这个块称之为脏块。脏块在写入磁盘前,是不会被踢出buffer的。

如果LRU中的脏块比较多,每次申请新的空间时,都要扫描很多脏块,但是又不能被淘汰。效率很低。

为此Oracle因为了脏LRU链表。专门用来记录脏数据块。

wKiom1XyQTKxUB7EAAGMimKuuHg494.jpg


当块被修改,并不会马上从LRU链表中移动到LRUW中。只有当Oracle需要淘汰数据块时,才会去扫描LRU链表,此时发现块为脏块,将数据块移动到LRUW链表中。


检查点链表

通过上面的描述,我们知道脏块在LRU和LRUW链表中都有。那么当dbwr写数据时,这两个链表都要扫描。首先效率比较低,并且无法保证先修改的数据块先被写入磁盘。

为此Oracle引入了检查点队列,该队列按照数据块第一次被修改顺序将脏块链接到一起。

dbwr写脏块时,只需读取检查点队列即可。

wKioL1XySGbxnJ1CAAFizzKI9-I567.jpg并且每个数据块与记录了日志条目的位置

wKioL1XySJyAgKoQAAda2T6MRp0420.jpg


redo log buffer

wKiom1XySO7DwH2oAAAwy1EVoTg025.gif

用户进程将redo entries 拷贝到redo log buffer中。LGWR负责将其写到磁盘中。

Redo entries contain the information necessary to reconstruct, or redo, changes made to the database by DML or DDL operations. Database recovery applies redo entries to data files to reconstruct lost changes.


共享池

wKiom1XySV_RSHDXAAA8dxh9Z90046.gif


Library Cache:

主要存放shared curosr(SQL)和PLSQL对象(function,procedure,trigger)的信息,以及这些对象所依赖的table,index,view等对象的信息。


Private SQL Areas与Shared SQL Area的关系

wKiom1XyS27zPaw5AABpIncp7-A402.gif


数据字典缓存

用来缓存系统数据字典表的内容,与普通表的缓存不同,普通表以块为单位缓存到buffer cache中。而数据字典缓存以行为单位,缓存到shared pool中的data dictionary cache中。


Server result cache

用来缓存sql或者plsql的执行结果。


大池:

 The large pool can provide large memory allocations for the following:

  • UGA for the shared server and the Oracle XA interface (used where transactions interact with multiple databases)

  • Message buffers used in the parallel execution of statements

  • Buffers for Recovery Manager (RMAN) I/O slaves


配置内存

Oracle提供了两个初始化参数用来配置内存自动管理

MEMORY_TARGET:sga+pga内存之和,Oracle自动分配SGA和PGA的大小。

MEMORY_MAX_TARGET:MEMORY_TARGET可以设置大小的上限。


SGA自动内存管理

设置初始化参数SGA_TARGET为非0值,并且将STATISTICS_LEVEL的值设置为TYPICAL或者ALL.


PGA自动内存管理

PGA_AGGREGATE_TARGET设置为非0值。

如果workarea_size_policy为auto则sort_area_size,hash_area_size等参数设置被忽略,如果workarea_size_policy为manual,则sort_area_size,hash_area_size等参数设置生效。


也可以手工配置其他各个内存池的大小当配置了内存自动管理时有配置了具体池的大小那么该配置为自动内存分配时的最小大小


查看内存情况

The following views provide information about dynamic resize operations:

  • V$MEMORY_CURRENT_RESIZE_OPS displays information about memory resize operations (both automatic and manual) which are currently in progress.

  • V$MEMORY_DYNAMIC_COMPONENTS displays information about the current sizes of all dynamically tuned memory components, including the total sizes of the SGA and instance PGA.

  • V$MEMORY_RESIZE_OPS displays information about the last 800 completed memory resize operations (both automatic and manual). This does not include in-progress operations.

  • V$MEMORY_TARGET_ADVICE displays tuning advice for the MEMORY_TARGET initialization parameter.

  • V$SGA_CURRENT_RESIZE_OPS displays information about SGA resize operations that are currently in progress. An operation can be a grow or a shrink of a dynamic SGA component.

  • V$SGA_RESIZE_OPS displays information about the last 800 completed SGA resize operations. This does not include any operations currently in progress.

  • V$SGA_DYNAMIC_COMPONENTS displays information about the dynamic components in SGA. This view summarizes information based on all completed SGA resize operations that occurred after startup.

  • V$SGA_DYNAMIC_FREE_MEMORY displays information about the amount of SGA memory available for future dynamic SGA resize operations.

请使用浏览器的分享功能分享到微信等