love wife love life —Roger的Oracle/MySQL/PostgreSQL数据恢复博客

Phone:18180207355 提供专业Oracle/MySQL/PostgreSQL数据恢复、性能优化、迁移升级、紧急救援等服务

Parallel Query 导致的ORA-04031

本站文章除注明转载外,均为本站原创: 转载自love wife love life —Roger的Oracle/MySQL/PostgreSQL数据恢复博客

本文链接地址: Parallel Query 导致的ORA-04031

一个朋友遇到ORA-04031问题。虽然这个错误是非常常见的,然而这里的Case 也有点让人为之震惊!

上述信息为Rac 节点1的信息,对于节点2,信息也基本类似,这里就不贴了。从日志来看,是p621出异常,根据这一点
我们可以判断为是并行进程出现了异常,接着从下面的ORA-04031错误也可以证实这一点。
ORA-04031: 无法分配 32792 字节的共享内存 (“shared pool”,”unknown object”,”sga heap(2,0)”,”PX msg pool”)

从这个错误来看,可以判断P621进程无法分别32792 byte的内存了。这部分内存是需要为Px msg pool进程分配。

这里首先说说PX msg pool是干什么的?

Px msg pool其实是用于Parallel 操作的。通常情况下这部分内存区域应该是从large pool中分配。然而很多业务系统中
由于设置不到,导致parallel 操作仍然使用shared pool的memory。这一点,我们稍后讨论。

接着我们看后面的日子发现PMON进程都无法获得latch了,然后这个时候系统已经不行了。 很明显这个问题的根源就是前面
的ORA-04031错误,这里我们需要分析下trace,来确认下,为什么进程会报错。

该trace文件(xx1_p485_28873.trc)的内容如下:

可以看到,PX msg pool请求获得32792 byte的内存大小,从什么地方申请呢? heap 2,也就是shared pool的第2个subpool。
但是却无法分配这么多,以至于报错,下面我们来看下subpool 2的实际情况:

可以看到gcs/ges resource/enqueue这部分内存都消耗了1.4g 左右,还是比较大的,另外ASM extent pointer array
也有300多m。这个可能跟asm的extent分配有关系,对于DW缓解,建议不要使用默认的uniform AU 1m,太小了。

总体来看,从这个subpool的使用情况来看,无法看出是不是碎片严重了。但是从dump下面的library 数据来看,也是
能看出一些端倪的,如下:

大家可以看到,SQL area 这里的reloads和invalids太高了。说明这个时间点shared pool的可用内存可能不多。虽然
从前面的dump看free memory还不少。 我们需要明白一点,Oracle消耗shared pool的内存,是需要连续的一段内存区域。

从这里来看如果如不是shared pool碎片严重那么可能就是有大的SQL操作。我们看该进程的信息发现该进程一直在等待

某个latch Child parallel query alloc buffer,如下:

这个latch Child parallel query alloc buffer 也就是在进行Px msg pool 内存分配的时候需要获得的,当内存分配完毕之后latch会立刻
释放,通常情况下,Oracle 对于Latch的申请和释放是非常之快的。很明显这里这个进程由于申请内存失败,导致latch也没有释放,还阻塞
了一堆的会话。

由于朋友这里没有其他的信息,所以很难准确的定位到是不是碎片或者其他的问题。但是从trace 里面也不难发现一些信息。前面提到进程
申请内存,势必就要看看下这个会话是什么操作了,不看不知道,一看吓一跳,如下:

大家可以看到,这个sql居然开了512个并行,如果把几个表的并行都加起来,高达584个。问题应用这里还不止这一个SQL。

对于并行查询,我们知道,即使你的并行度设置的再高,也不一定能用这么多,因为这是受限制数据库参数的。不过,悲剧的是,
他这里默认参数都是比较大的。cpu_count=114,默认的dop都高达228。parallel_max_server更是高达好几千了。

还有一点,他的参数parallel_force_local是ture,这也导致parallel进程只能在单个实例进行分配。

其实上述信息都不是重要的,更重要也是更致命的一点的是,并行查询使用的Px msg pool居然从shared pool了进行分配了。

我看信息,他这里的large pool设置高达10gb啊,其实是完全没用派上用场。

对于Px msg pool,如果你的数据库PARALLEL_MIN_SERVERS比较大(这里就是比较大),那么当数据库启动时候,可能Px msg pool
就会消耗不少的内存的。

对于Parallel操作的内存消耗Px memory,可以从large pool分配,也可以从shared pool进行分配。这里需要注意,即使你设置了
large pool,如果不满足下面的条件,那么Px memory仍然会从shared pool去分配。

1) parallel_automatic_tuning 参数设置为auto
2) _PX_use_large_pool 隐含参数设置为true
3) 使用ASMM ,即使设置了sga_target 或 memory_target.

很遗憾的是,他这里3点都不满足。

Leave a Reply

You must be logged in to post a comment.