Shared Pool Latch和Library Cache Latch竞争

Shared Pool Latch和Library Cache Latch竞争:

这两个Latch是Shared Pool管理中最重要也是最常见的Latch竞争。

Shared Pool Latch用于共享池中内存空间的分配和回收,如果SQL没有充分共享,反复解析,那么将会不断请求Shared Pool Latch在共享池中分配空间,由此可能造成非常严重的CPU消耗。

Library Cache Latch用于保护Cache在内存中的SQL以及执行计划等,当需要向Library Cache中增加新的SQL时,Library Cache Latch必须被获得。在解析SQL过程中,Oracle需要搜索Library Cache查找匹配的SQL,如果没有可共享的SQL代码,Oracle将全新解析SQL,获得Library Cache Latch向Library Cache中插入新的SQL代码。Library Cache Latch的数量受一个隐含参数_kgl_latch_count控制,其缺省值为大于或等于CPU_COUNT的最小素数,最大值不能超过67。

可以简化一下SQL的执行过程,以说明这两个Latch在SQL解析过程中所起的作用。

⑴ 首先需要获得Library Cache Latch,根据SQL的HASH_VALUE值在Library Cache中寻找是否存在可共享的代码。如果找到则为软解析,Server进程获得该SQL执行计划,转向第⑷步;如果找不到共享代码则执行硬解析。
⑵ 释放Library Cache Latch,获得Shared Pool Latch,查找并锁定自由空间。
⑶ 释放Shared Pool Latch,重新获得Library Cache Lacth,将SQL及执行计划插入到Library Cache中。
⑷ 释放Library Cache Latch,保持Null模式的Library Cache Pin/Lock。
⑸ 开始执行。

通过以上过程可以看到,如果系统中存在过度的硬解析,系统的性能必然受到反复解析、Latch争用的折磨。通过查询v$sysstat视图获得关于数据库解析的详细信息:

sys@NEI> select name,value from v$sysstat where name like 'parse%';
NAME                                  VALUE
------------------------------ ------------
parse time cpu                         6565
parse time elapsed                   507494
parse count (total)                  680519
parse count (hard)                    18731
parse count (failures)                   39

通过(parse count (total) - parse count (hard))/parse count (total)得出的软解析率经常被用作衡量数据库性能的一个重要指标。

对于version_count过高的问题,可以查询v$sql_shared_cursor视图,这个视图会给出SQL不能共享的具体原因,如果是正常因素导致的,相应的字段会被标记为“Y”;对于异常的情况,查询结果可能显示的都是“N”,这就表明Oracle认为这种行为是正常的,在当前系统设置下,这些SQL不应该被共享,那么可以判断是某个参数设置引起的。和SQL共享关系最大的一个初始化参数就是cursor_sharing。当cursor_sharing参数为similar,并且数据库存在相关柱状图(histograms)信息时,对于每一条新执行的SQL,Oracle都通过硬解析以获得更为精确的执行计划,这最终导致了version_count过高,这是cursor_sharing=similar的正常行为,并非Bug。

了解了这个行为之后,解决这个问题也就不复杂了,可以将cursor_sharing设置为Exact或者Force以避免此问题,或者通过删除柱状图(Histograms)来防止不必要的硬解析,实际上,如果数据不存在失衡分布,我们也不必要收集柱状图信息。

从中得到启是,当需要设置某些特殊的参数来影响数据库的行为时,必须了解这些设置会给数据库带来的影响,这样一方面可以避免问题的出现,另一方面在问题出现时,我们可以快速地发现问题根源并解决问题。

- The End -