这个latch Child parallel query alloc buffer 也就是在进行Px msg pool 内存分配的时候需要获得的,当内存分配完毕之后latch会立刻释放,通常情况下,Oracle 对于Latch的申请和释放是非常之快的。很明显这里这个进程由于申请内存失败,导致latch也没有释放,还阻塞了一堆的会话。
由于朋友这里没有其他的信息,所以很难准确的定位到是不是碎片或者其他的问题。但是从trace 里面也不难发现一些信息。前面提到进程申请内存,势必就要看看下这个会话是什么操作了,不看不知道,一看吓一跳,如下:
MERGE INTO xx.xxxx_A A
USING (SELECT /*+ parallel(a,512) parallel(b,8) */
:B2 STATIS_MONTH,
NVL(B.PROV_ID, '000') PROV_ID,
COUNT(DISTINCT A.SERV_NUM) CNT
FROM (SELECT DISTINCT SERV_NUM
FROM xxx.TDW_XXXXX_MIGU_MEMBER_M A
WHERE STATIS_MONTH = :B1
AND MEMBER_LVL = '1'
AND MEMBER_STAT IN ('1', '0')
AND EXISTS (SELECT /*+ parallel(b,64)*/
1
FROM xxx.TKR_DEV_XXXXX_CORE_M B
WHERE A.SERV_NUM = B.SERV_NUM)) A,
xxx.VDW_NUMBER_SEGMENT B
WHERE SUBSTR(A.SERV_NUM, 1, 7) = B.SEGMENT(+)
GROUP BY B.PROV_ID) B
ON (A.STATIS_MONTH = B.STATIS_MONTH AND A.PROV_ID = B.PROV_ID)
WHEN MATCHED THEN
UPxxTE SET CORE_NRML = CNT
大家可以看到,这个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点都不满足。