昨天对latch做了一个入门,接着我们来看看比较面熟的几个latch。

首先是非常著名的cache buffer chains latch,简称cbc latch(后文o小白都这么打了,不然太长了……),g一下话可以看到这样的案列和解释不计其数了,那这里也介绍一下。那要说清楚的话就要从原理说起了。一个被读入buffer cache的数据块的头部我们称之为buffer header。oracle借助hash算法,通过对buffer header里的数据块地址进行hash运算以后生成hash bucket,而所谓的hash chain就是一个hash bucket的所有buffer header所串起来的一个链表,那cbc latch自然就是用来管理hash chain的并发操作的。

清楚了原理之后再想一下,不难想到怎么会引起这个种类的latch争用的,如果有很多的session同时集中对某些数据块进行访问的话,那自然会引起这个latch的争用,那这些被多个session频繁访问的数据块我们一般叫做热块。

那清楚了以上的原理我们来模拟看看。介绍一下实验的背景,为了模拟热块,我们新建一张表,cbctest,就一个字段id,就一条记录,然后我们执行下面的脚本。

频繁对单一表进行查询(o小白加了好几次0才使实验结果明显了点……果然还是没见过大世面的dba啊……),同是开三个session,执行上述的脚本。在执行脚本的同时,从下面的那张图中我们可以看到,确实是cbc latch引起了session的等待:

那通过这个小实验,相信大家对这个cbc latch有了一定的了解,在实际应用中,如果发现了这样的情况,那自然是由于sql语句执行效率低下和热块引起的。对于前者,如果sql语句执行效率低下,必须扫描大量的数据块后才能返回应有的数据,那在有众多session频繁访问的情况下,必然会出现大量cbc latch争用的情况,所以说sql语句的执行效率相当重要。而cbc latch由于热块而造成的可能性则更大,考虑是不是考虑使用分区(有关于分区之前有介绍)之类的,热块单独绝对可以写成一文,学习之后o小白会和大家分享。

那和cbc latch最相关的就是,cache buffers lru chain latch。这个和Linux盘块缓冲池的那个空闲队列链的结构有点相似(赵老师的学生们应该印象很深的),简单来说,就是oracle根据使用被使用的先后顺序把buffer挂在一条链表上,先被使用的buffer挂在链表的后面,如果有新的数据请求,则从这条链表中从尾部往前扫描,那这条链表就是lru链表。那所谓的cache buffers lru chain latch就是保护这条链表的latch。

要解决这个latch事件,可能最理想的办法就是增大buffer cache,当然也有隐藏参数_db_block_lru_latches来指定latch的数量,但是不推荐这么做,这个参数和系统的cpu数目有关,胡乱设定可能影响数据库的性能。

ps:这期latch其实和oracle的内存结构buffer cache有着很深的关系,o小白原来也只是了解buffer cache这个名词,对他的结构和实现原理没多大兴趣,但是现在看来这些知识也是很必要的,看来o小白可能在锁的专题完结后就oracle的内存结构啊,进程啊这些做一些学习和分享了。