oracle学习篇:四、内存管理

4 内存管理

4.1 SGA管理

4.1.1 SGA的组成

buffer cache,shared pool,redo log buffer,large pool,java pool,streams pool

select * from v$sgainfo;

4.1.2 SGA与共享内存

SGA的设置在Linux/UNIX上和一个操作系统内核参数有关,这个参数是shmmax。

在Solaris上,该参数由/etc/system文件中shmsys:shminfo_shmmax定义;在linux上,该参数由/proc/sys/kernel/shmmax参数定义。

shmmax内核参数定义的是系统运行的单个共享内存段的最大值,如果该参数设置小于SGA设置,那么SGA仍然可以创建成功,但是会被分配到多个共享内存段。

在windows系统中,由于系统采用多线程服务器(所有oracle进程实际上都是一个进程中的线程),所以不存在共享内存的问题,无需进行特殊设置。

 shmmax内核参数定义的是系统运行的单个共享内存段的最大值,如果该参数设置小于SGA设置,那么SGA仍然可以创建成功

查看shmmax值:

more /porc/sys/kernel/shmmax

查看操作系统版本:

cat /etc/redhat-release

查看操作系统发行版号:

uname -r

ipcs查看共享内存的分配:

ipcs -sa

可以看到为了创建oracle的SGA,系统共分配了27个共享内存段(shared memory segments)

针对一个后台进程,使用pmap工具可以看到每个共享内存段的地址空间

ps -ef|grep dbw

pmap 2333

echo 1073741824>/proc/sys/kernel/shmmax

这里修改为1GB,对于shmmax文件的修改,系统重启后会复位,可以通过修改/etc/sysctl.conf文件使更改永久化。

vi /etc/sysctl.conf

添加:

kernel.shmmax=1073741824

重启数据库使之生效

如果没有修改kernel参数,oracle在启动过程中就会在alertorcl.log文件中记录警告。

SGA设置过大,超过物理内存;数据库异常关闭,后台进程未正常退出,可通过ipcrm命令强制释放该共享内存段。

4.1.3 SGA管理的变迁

一些建议视图:

select * from dba_views where view_name like '%ADVICE%';

4.2.1 PGA
PGA:程序全局区,是服务器进程使用的一块包含数据和控制信息的内存区域,pga是非共享的内存,在服务器进程启动或创建时分配,通常来水,pga中包含私有sql区(存放绑定信息、运行时内存结构等)和session信息等内容。

所有服务器进程分配的PGA总和通常被称为PGA合计(aggregated pga)

对于pga_aggregate_target参数的设置,oracle提供这样一个建议方案

对于OLTP系统:

pga_aggregate_target=(total physical memory * 80%) * 20%

对于DSS系统

pga_aggregate_target=(total physical memory * 80% ) *50%

也就是说,对于一个单纯的数据库服务器,通常需要保留20%的物理内存给操作系统使用,剩余80%可以分配给oracle使用。oracle使用的内存分为两部分sga和pga,那么pga可以占用oracle消耗总内存的20%(oltp系统)~50%(dss系统)

v$process视图增加了相应字段用来记录进程的pga耗用

ps -ef|grep ora|head -l

SQL在工作区中以3种方式执行:

optimal(优化方式):指所有处理可以在内存中完成;

onepass:大部分操作可以在内存中完成,但是需要使用到磁盘操作;

multipass:大量操作需要产生磁盘交互,性能极差。

通常对于pga的优化目标,就是使得optimal的执行尽量高,也就是尽量在内存中完成所有排序等操作;同时使multipass操作尽量低,也就是要使磁盘交互尽量低。

在v$pgastat中有这样一个条目global memory bound,该条目记录数据库允许的最高pga内存使用量,可以从不同的pga参数设置来观察一些oracle允许的pga上限。

4.2.2 PGA调整建议

select pga_target_for_estimate,pga_target_factor,estd_pga_cache_hit_percentage,estd_overalloc_count from v$pga_target_advice;

hit最高,消除过载。

4.3 oracle的内存分配和使用

oracle数据库在系统占用的内存分为两个部分:SGA和PGA。

根据oracle的建议,oracle最多可以使用80%的物理内存,其余20%保留给操作系统用,在这80%的内存中,对于OLTP系统,oracle建议分配20%给PGA使用;对于DSS系统,可以分配50%给PGA使用。

如果oracle耗用的内存过高,甚至超过了系统的物理内存,那么系统的性能就会受到严重的影响,当系统执行任务时,如果没有足够的内存,那么系统就会进行分页或交换,以完成当前活动事务。

当系统执行分页时,会将当前没有使用的信息从内存转移到硬盘上,这样就可以为当前需要内存的程序分配内存。如果频繁发生分页,系统性能就会严重降低,从而导致很多程序的执行时间变长。

当系统执行交换时,会将某些进程所分配的不活跃内存页(根据LRU算法)从内存转移到硬盘上,这样另一个活动进程就可以得到所需要的内存。交换基于系统循环时间。如果交换太过于频繁,系统甚至会出现宕机。

4.3.1 诊断案列:SGA与Swap

案列描述:用户报告,服务器启动一段时间后,无法建立数据库连接。重新启动几分以后,再次无法连接。

操作系统:SunOS5.8,系统无法正常使用

(1) 登陆数据库,检查系统进程

ps -ef|grep ora

发现后台进程正常

(2)检查警报日志文件

skgpspawn failed:该提示说明系统无法fork新的数据库进程,数据库无法spawn a new session

报错:category=27142,即ora-27142,报错内容:无法创建一个新进程。

(3)尝试连接数据库

报错:超出内部限制,通常说明某些系统资源不足。

(4)检查系统日志

检查系统日志信息,发现大量失败的su操作,有Swap区不足的报告

基本可以判断是交换区的问题,当然和oracle SGA设置有关。

(5)检查系统内存及交换区使用

top

发现物理内存仅为1GB,free部分为34MB,交换区使用了752MB,仅Swap Free部分仅余10MB。由此可知,系统内存严重不足,Swap区不足。

(6)检查数据库的SGA设置

show sga;

发现SGA设置为600MB,这个SGA设置过高。

对于RAM小于1GB的系统,Dedicated模式下,通常建议oracle的sga一般不应超过1/2物理内存,sga之外还应考虑到pga及操作系统的内存分配。

(7)调整内容

减小sga,为系统保留足够的内存;

为系统增加Swap区

cd /export/home1

mkdir swap

cd swap

mkfile -v lg swapfile1

swap -a /export/home1/swap/swapfile1

swap -s

至此系统恢复正常,问题解决。

(8)问题总结

oracle数据库问题的解决从来就离不开操作系统,很多时候必须通过操作系统一级的手段来诊断并解决问题。

关于操作系统,一般Swap区的推荐指为2xSwap。

如果物理内存很大,不一定要设置成2倍,可以=或小于,若内存超过32G则完全可以设置Swap为16GB。

如果物理内存过小,在系统繁忙期间,产生大量交换无法换到磁盘,就会出现问题。

4.3.2 诊断案例二:SGA设置过高导致的系统故障

案例描述:大型生产系统,问题出现时系统累计大量用户进程,用户请求得不到及时响应,新的进程不断尝试建立连接,连接数很快被用完。最后系统处于挂起状态,无法进行服务响应。

(1)登陆数据库,检查警告日志文件

WARNING:aiowait timed out 2 times

说明系统异步IO出现问题,每次warning间隔时间为10分钟。

(2)检查共享内存设置

说明系统内核参数设置不合理或者和sga不匹配,检查system配置文件

cat /etc/system

发现最大共享内存段设置为4GB

(3)检查SGA设置

发现sga设置接近7GB(超过4GB,oracle将分配多个共享内存段)

(4)交换区问题

top

memory:8192M real,118m free 12G swap in use 11G swap free

物理内存几乎耗尽,使用了12GB的Swap

至此可以初步做出以下判断:由于SGA设置过大,导致运行时产生大量交换,大量Swap交换进而引发磁盘I/O问题。

大量交换导致数据库性能急剧下降,进而导致用户请求得不快速响应,堵塞,累计,直至数据库失去响应。

(5)解决方案

缩小SGA

(6)系统调整后状态

top

稳定

(7)一点总结

(8)后续研究

异步I/O问题

4.3.3 诊断案例三:如何诊断和解决CPU高度消耗(100%)问题

这类问题通常是因为系统中存在性能低下甚至存在错误的SQL语句,消耗了大量的CPU所致。

问题描述:系统CPU高度消耗,系统运行缓慢

(1)top命令

发现在进程列表里,存在两个搞CPU耗用的oracle进程

(2)找到存在问题的进程信息

ps -ef|grep 20521

ps -ef|grep 20845

(3)捕获存在问题的SQL语句

select /*+ordered*/ sql_text from v$sqltest a where (a.hash_value,a.address) in (select decode(sql_hash_value,0,prev_hash_value,sql_hash_value),(sql_address,0,prev_sql_address,sql_address) from v$session b where b.paddr=(select addr from v$process c where c.spid='&pid')) order by piece asc;

(4)连接数据库,找到问题sql及进程

这段代码就是CPU疯狂消耗的原因,找出这段代码的问题,看是否可以通过优化提高其效率,减少资源消耗。

(5)进一步跟踪

如果需要进一步的跟踪详细信息,可以用过dbms_system包来进行;

exec dbms_system.set_sql_trace_in_session(45,38991,true);

(6)一点说明

很多时候,高CPU消耗都是由于问题SQL导致的,所以找到这些SQL通常也就找到了问题所在,通过优化调整通常就可以解决问题。

但是有时候可能会发现,这些最消耗CPU的进程是后台进程,这一般是由于异常、BUG、或者恢复后的异常导致的,那么就需要具体问题具体分析了。

第四章完

猜你喜欢

转载自www.cnblogs.com/myheart-new/p/11753784.html