Parallel Query 导致的ORA(7)

这个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点都不满足。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/40a5d2857651370c883e5166669d2e40.html