Latch:shared pool
Latch:library cache
我们知道Oracle通过SHARED POOL来实现SQL共享,减少硬解析等。而SQL的相关信息,如:SQL语句文本,SQL执行计划等都存放在SHARED POOL的Library Cache部分
其中Library Cache的结构如下图
可以看到其结构和BUFFER CACHE类似,为了能够在Library Cache中快速的查找到对应的SQL,也是通过将不同的SQL语句通过HASH函数HASH后放置到对应Hash Bucket来保存的。 下面看看图中黄色的块(右上角标注着:Object Handle):
1) 这个块也就是所谓的Library Cache Object Handle,这个Handle描述Library Cache中对象的一些属性,如名称(Name),所属的命名空间(Namespace)、标记(Flags)、指向对
象所处的内存地址的指针(Heap 0)等。对应SQL来说,这个可以算是父游标。
2) Heap 0用来存放与对象有直接关系的一些信息,比如对象类型、对象相关的表、实际的执行计划等
3)同一个Hash Bucket中的Object Handle相互链接形成一条Chain。
关于Library Cache更详细的可以查阅Julian Dyke的LibraryCacheInternals.ppt。 Eygle网站上也有一张简洁的图:
下面先看SQL的的整个执行过程来,然后再看看执行过程中是怎么用到SHARED POOL的相关Latch。
1) 当客户端执行一条SQL,这时候Oracle首先将SQL文本转换成ASCII值,然后根据HASH
函数计算该SQL对应的Hash Value。
2) 根据得到的Hash Value到Library Cache中查找对应的Bucket,然后查找Bucket里是否存在该SQL?
(Y) 如果存在,则接下来查找对应的子游标,这个时候将一直持有Library Cache
Latch,直到找到对应的执行计划。然后释放Latch。(软解析)
(N) 如果不存在,就要去SHARE POOL里面获得可用空间,来生生成对应的Library Cache对象。这个时候就要获得Shared Pool Latch在SHARE POOL的Free List(SHRAE POOL通过Free List管理Free Chunk)查找可用的空间,之后释放Shared Pool Latch。接下来就开始进行硬解析过程,将执行解析后的执行计划等信息记录到Library Cache中,这个整个过程消耗大量的CPU,同时将一直持有Library Cache Latch,一直到硬解析结束。(硬解析)
根据获得的执行计划,开始执行SQL,如:到BUFFER CACHE查询数据等。
整个逻辑如下如:
当出现Latch竞争严重的时候:
如果同时出现大量的Share Pool Latch和Library Cache Latch的话,根据上面的逻辑那说明数据库中存在大量的硬解析,这个时候就要查找那些SQL没有绑定变量。
如果只是出现大量的Library Cache Latch的话,那么可能有两种情况:
1) 当持有Library Cache Latch查找Bucket对应的Chain时候,发现存在高Version的SQL,这个时候就要扫描这些对应的子游标,整个过程将一直持有Latch,导致其他会话获取不到Latch进行操作。
2) 大量的并发请求,而且不能实现SQL一次Parse Call多次Execution。
字典缓冲区: dictionary cache,也叫row cache;
用于保存数据字典信息:如表空间相关信息、用户权限、objects信息、histogram信息等。
字典缓冲区在大小无法直接调整,只能通过调整共享池大小来调整字典缓冲区大小。
SYS@ bys3>select pool,name ,bytes/1024/1024 MBfrom v$sgastat where name like 'row cache%';
POOL NAME MB
------------ -------------------------- ----------
shared pool row cache childlatch .004959106
shared pool rowcache 4.12324524
从Oracle 9i开始,Shared Pool可以被分割为多个子缓冲池(SubPool)进行管理,以提高并发性,减少竞争。
Shared Pool的每个SubPool可以被看作是一个Mini Shared Pool,拥有自己独立的Free List、内存结构以及LRU List、shared pool latch。同时Oracle提供多个Latch对各个子缓冲池进行管理,从而避免单个Latch的竞争(Shared Pool Reserved Area同样进行分割管理)。从10G开始,每个SubPool由4个SUB PARTITION组成。
每四个CPU分配一个SubPool,最多可以有7个。Shared Pool Latch也就从原来的一个增加到现在的7个。
在Oracle9i中,每个SubPool至少为128MB。
10G-10.2.0.3,每个SubPool至少为256MB
10.2.0.3之后,最少为512M。
_kghdsidx_count 隐含参数:ORACLE启动时,优化根据此参数设置SubPool数量。
NAME VALUE ISDEFAULT ISMOD ISADJ
------------------------------------------------------------------------
_kghdsidx_count 1 TRUE FALSE FALSE
从ORACL 10G开始,ORACLE进程在某个SubPool中请求内存失败,会到下一个SubPool中请求---过小的SubPool碎片问题可能更严重--ORA-4031出现机率更大。
过多的SubPool还会带来更高的管理协调成本。
比如以下错误就是与SubPool相关:
ORA-04031: unable to allocate 4216 bytes of sharedmemory
("shared pool","unknownobject","sga heap(2,0)","library cache")
SQL语句的缓存结果集参考:http://www.itpub.net/thread-846890-1-1.html
Latch:redo copy
Latch:redo allocation latch
当一个进程在修改数据时候将会产生Redo,这个Redo首先在PGA中保存。然后进程需要获取Redo Copy Latch(这个Latch的个数由隐含参数_log_simultaneous_copies决定),当获得Redo Copy Latch后,进程接着获取Redo Allocation Latch来分配Redo Log Buffer中的空间,空间分配完成后,释放Redo Allocation Latch。然后进程把PGA里临时存放的Redo信息复制到Redo Log Buffer,复制完成后,释放Redo Copy Latch