上篇算是对latch:cache buffer chain做了一个简单的说明,相对来说latch还是不属于oracle比较表层的东西,可能大多数的初学者看不懂(高手们一笑而过),不过没关系,混个脸熟就行,相信经过一段长时间的积累和学习,总也有明悟的一天嘛。

上次的两个latch主要还是和oracle的内存结构中的buffer cache有关,那这次通过题目想必也能看到,这次我们的主题是和shared pool有关的两个latch。

那 这里简单说一下就是shared pool主要是负责sql语句和pl/sql的解析,而其中包含library cache和dictionary cache两部分,dictionary cache是为了加快sql的的解析速度,放了一些表的定义啊,约束啊,权限关系啊这类的东西,不需要过多关注。而library cache中是比较重要的部分,存放的sql语句,执行计划等等,是我们要关注的部分。

在shared pool中最小的内存分配单位我们称为chunk,chunk里是一段连续的内存空间,在shared pool里所有可用的chunk(也就是即没有被library cache获得也没有被dictionary cache占用的空闲的chunk)会被串起来形成一个列表,形成一个bucket。(这个是不是和buffer cache有点相似?还没完呢,library cache也是非常相似的结构,这种结构在oracle里非常常见)每个bucket上挂一定数量的chunk,并且chunk的大小是会逐渐递增的。当 某个进程需要用到chunk的时候就会对bucket进行扫描,并进行分配。而对bucket的扫描、肥培和管理都是在shared pool latch的保护下进行的。

原理是弄清楚了,但是我们必须还要弄清楚library cache。

library cache也是使用hash bucket来管理的,每个hash bucket上串的是对象的句柄,句柄包含了对象的属性,而句柄则是由library cache里面的chunk组成的。一条sql语句进入library cache后首先转化为ASCII数值,然后对这些数值进行hash运算,其中也包括形成句柄所需要的属性(名称、命名空间啊等等),最后得到的就是 hash bucket的编号。

得到这个hash bucket的编号以后………………我们先暂停一下,插播一段广告!哦不是广告,是插播一段解析……

哦,那解析解析到底什么是解析呢,解析又分为什么步骤呢?我们小小的解释一下:

解析呢就是将sql语句翻译成oracle能够识别的语句,就叫解析了。

硬解析就是某条sql语句被第一次解析的过程,具体如下:

首 先进行文法检查,就是sql语句有没写错,然后是去校验对象是否存在并且进行对象的翻译,权限的检查。然后是重头戏,就是通过优化器创建执行计划,这步是 非常消耗cpu资源的,然后就是将执行计划和相关内容装载到前面所说的句柄里面去。(确切的说是句柄里面最重要的部分——heap里面去,关于heap以 后再说,这里要说的是这个东西和pin有关系,认真看o小白日志的朋友们应该有印象的,大家可以好好想想)

而软解析就是省掉某些步骤,主要是创建执行计划和装载的步骤,当然各种不同的情况下可以跳过更多的步骤,甚至跳过所有的步骤,按下不表,以后详谈。

然后回到得到这个hash bucket的编号,得到编号以后进入bucket里寻找,看看是不是有相同的sql被解析过了,如果找不到,那自然要去shared pool里面找一块chunk进入library cache了。

好 了,说到这里大家应该知道了,shared pool latch自然就是在获取chunk的时候被争用的,而且问题产生的原因也很突出了,就是有大量的sql语句需要硬解析,也就是有很多不一样的sql语 句,那这里注意了写sql语句就算是大小写不一样也是重新进行硬解析的,还有where条件里的变量不同,这些都必须进行硬解析,所以说如果出现了大量的 这个latch争用,很有可能是由于应用中sql书写不统一不规范,没有用绑定变量造成的,这是sql语句书写的大忌。

而library cache latch则是在整个解析的过程中都会被持有,也就是说基本上有了shared pool latch都会有library cache latch(在oracle早期的版本中8i前,由于chunk这部分没处理好,导致有了非常小的chunk几乎是不可用的,但是扫描却必须还是要扫描, 会导致大量的shared pool latch争用,后来经过了改善,使chunk更加均匀地分布在每个bucket上,这样hold shared pool latch的时间要短很多),出现这样的情况就是上面所说的硬解析过多的问题。如果shared pool latch不多,但是library cache latch过多,当然还是要从应用出发,看看是不是可以调整sql语句,也可以设置处死豪华参数session_cached_cursors,这样的话 执行计划就会转移到session的PGA里,那相同的session发出相同的sql语句则直接从PGA里取出执行计划,但是这样做却要花费大量的内 存。当然,这两种latch如果发生的话,主要还是有sql语句书写不当引起的。

然后做个小实验,模拟一下这个latch。

 

 脚本很简单,无非就是模拟一些需要硬解析的sql语句,然后做一个awr可以看到。

可以看到有library cache这行相当高,非常简单的一个实验。

相信大家对这两个latch也有了一定的了解,再接再厉,latch快要终结了哦~