allaboutOraclememory-Oracle的内存管理(八)

2014-11-24 16:56:09 · 作者: · 浏览: 2
时同时也遵循64K的最小粒度,来提交倍数于这个粒度值的内存页。许多用户会话经常分配许多小于64K的内存,这就导致地址空间出现碎片,因为许多64K区只有两个页被提交。

一旦地址空间被用户会话占满了后,如果要再创建一个新会话,就会存在无法分配到地址空间的危险。将可能报以下错误:

ORA-12500 / TNS-12500

TNS:listener failed to start a dedicatedserver process

也可能报这些错误:

o ORA-12540 / TNS-12540 TNS:internal limit restriction exceeded

o NT-8 Not enough storage is available to process this command

o skgpspawn failed:category = ....

o ORA-27142 could not create new process

o ORA-27143 OS system call failure

o ORA-4030 out of process memory when trying to allocate ....

因为地址空间碎片问题和DLL被载入了oracle服务进程的地址空间,这些错误很可能发生再当Oracle进程占用大概1.6G~1.7G(可以通过任务管理器或TopShow查看)时。

2.4.4.1.会话内存大小设置

我们前面说了,一个进程的全部内存大小被限制在2G以内。因此,对于一个有许多用户同时访问的系统,要考虑这些会话总内存小于2G - SGA的大小。

下列参数会影响每个会话的内存大小(这些参数前面都有介绍):

o bitmap_merge_area_size

o create_bitmap_area_size

o hash_area_size

o open_cursors

o sort_area_size (sort_area_retained_size)

在没有设置PGA_AGGREGATE_TARGE(这个参数能尽量但不一定使所有会话PGA之和在指定范围内)参数时,需要调整这些参数,以使所有会话占用内存与SGA之和小于2G。过多的使用PL/SQL结构体(如PL/SQLTABLE、ARRAY)也会导致会话内存增大。

2.4.4.2.ORASTACK修改线程堆栈大小

Oracle提供了ORASTACK工具让用户内修改Oracle执行程序创建会话、线程时的默认堆栈大小。当ORASTACK应用于一个可执行程序时,它会修改程序头部的、定义使用创建线程API函数所指定默认堆栈大小的二进制区,以修改默认堆栈的大小。没有必要去修改线程提交页数的默认值,因为它们是从堆栈中请求到的。当用户非常多时,通过减少每个创建在Oracle中会话堆栈大小,可以节省大量内存。比如,一个1000用户的系统,将堆栈从1M降为500K后,能节省出1000 *500K = 500M的地址空间。

在需要使用ORASTACK来降低现场堆栈大小时,你需要测试你的系统以保证新的堆栈大小能确保系统正常运行。如果堆栈大小被缩小到Oracle服务端所必须的堆栈大小以下,就会产生堆栈溢出错误,用户进程就失败(通常报ORA-3113错误),并且在alert log中不会有报错而且页不产生trace文件。Oracle一般不推荐将堆栈改到500K以下(尽管不少系统在300K时也能正常运行)。

ORASTACK必须修改所有能在oracle中创建线程的进程,使用语法如下:

  orastack  executable_name  new_stack_size_in_bytes

下面的例子将堆栈改为500K:

  orastack oracle.exe  500000
  orastack tnslsnr.exe 500000
  orastack svrmgrl.exe 500000
  orastack sqlplus.exe 500000

在使用ORASTACK之前必须保证没有任何oracle进程正在运行。

此外,如果有程序在本地连接(没有通过SQL*NET)到Oracle,也要先停止(如在本地运行sqlplus连接了实例)。

2.4.4.3.会话内存如何释放、线程如何结束

当会话成功结束后,它会按用Win32 API函数VirtualFree来释放它的内存,调用此函数时,需要指定MEM_DECOMMIT | MEM_RELEASE标识。当所有内存被释放后,堆栈也被释放,将Oracle进程中指向完成的会话的地址空间空闲出来。

如果一个用户会话被异常结束,它将不会释放它所分配的内存,这些内存页会被继续保留在Oracle进程的地址空间中,直到进程结束。会话的异常结束可能由以下原因导致的:

oShutdown abort.

oAlter session kill session.

oorakill杀掉的会话.

o Oracle管理助手for Windows:kill session.

o其他杀线程的工具(TopShow工具提供了杀线程的功能)

Oracle建议尽量少使用以上方式(命令),特别是shutdown abort(这种停止实例的方法所带来的问题还不止这个)。当调用shutdown abort时,Oracle会调用Win32 API函数TerminateThread来中止每个用户会话,这个命令将直接杀掉线程而不释放它们的内存。如果系统已经接近2G地址空间的限制,Oracle实例再次启动要分配内存时就会产生问题。唯一释放Oracle全部内存的方法是停止和启动Oracle服务(服务OracleService)。

如果windows NT下的系统需要能被许多用户访问,可以通过以下措施来优化内存的使用:

o降低相关的PGA、UGA内存参数(如SORT_AREA_SIZE);

o降低SGA的参数;

o使数据库作业队列数(参数job_queue_processes控制)和并行查询slave(参数parallel_max_servers控制)最小,因为它们也会导致Oracle进程创建线程;

o使用ORASTACK降低会话、线程堆栈大小到500K;

o考虑使用MTS模式;

o考虑将Windows NT升级到Windows NT企业版;

o考虑升级硬件以支持Intel ESMA(Extended. ServerMemory Architecture,扩展服务内存架构)