简单叙述下故障情况:
一套生产库在晚上跑批期间,增加了一项大事务,该大事务一直未提交,直到所有数据都跑完为止。而由于该大事务一直持有事务所,造成其他业务处于enq:TX-row lock contention.
正常情况下,enq:TX-row lock contention不会引发cpu、内存级别的故障,但当时由于大量的enq:TX-row lock contention,且加上当数据库在跑批,造成pga内存的分配持续增长,到高峰时期,pga增长到60g左右,造成服务器内存严重不足,发生大量换页操作,甚至无法连接主机,即使偶尔连接上后也无法执行命令,报内存不足。。。
最后只好对主机进行硬重启,切换到备机。。。
后续:
后面的处理就交由开发人员处理了,这个未提交的大事务不出意外是要被封杀掉了。。。
事故对我的启发:
首先,关于pga的认识。
在10g和11g的版本中,show parameter pga可以看到的参数,也就孤零零的一个pga_aggregate_target
对于此参数,我一直理解成是限制pga所能占用的OS内存大小,而此次事故,该值在库上设置为9g,但故障期间却暴涨到60g,说明该参数并不是一个限制型参数,而只是一个建议型的。后经查阅资料发现,pga与sga不同,sga可以通过sga_max_size值限制其最大值,而pga则是按需分配,当大量并发出现的情况下,pga的实际大小会超过pga_aggregate_target的值。
既然牵扯到并发,就不得不提下参数sessions和processes,每一个session在oracle建立连接,都需要分配一定大小的pga,也就意味着,即使sessions设置为3000,但当系统内存方面不足够大,不足以分配到3000个会话的pga内存的话,并发数便达不到3000这个阈值。甚至活动会话数只有几百多个,便将内存沾满,造成系统故障。。。
网上对于一个session占用pga大小的说法,有说2,3兆,有说4,5兆,具体占用多少pga大小,可以通过查看视图v$process计算。
在11g的版本中,关于内存管理这块,多了memory_target和memory_max_target的参数,这个memory_max_target很有误导性,其中的max值会让人私以为是现在sga和pga的总大小,查了下metalink上的文档:MEMORY_MAX_TARGET CAN BE EXCEEDED (Doc ID 1269898.1)
可知,memory_max_target这个参数和pga_aggregate_target一样,也是可以被超越的。
如此看来,在10g和11g的版本中,sga的大小可以被强制限制在一定范围,但pga就存在不确定性了,会随着会话数的增长而增长,直至攻占掉所有物理内存。。。
正所谓魔高一尺道高一丈,这个问题在12c中终于被oracle解决了。
在12c中,新增了参数pga_aggregate_limit,用于限制pga所能使用的物理内存大小。
那么在10g,11g等版本中,pga就没法限制了吗?目前看来确实没有好的办法,只能考虑从连接数,以及系统层面限制oracle内存使用的方面入手。
总结一下:
关于oracle,很多东西都是停留在当初想当然的认知层面,并没有验证是与否,还需继续学习。另外,最近状态很差,心态更差,急需调节。