library cache 的一些内部机制

Library cache是Shared pool的一部分,它几乎是Oracle内存结构中最复杂的一部分,主要存放shared curosr(SQL)和PLSQL对象(function,procedure,trigger)的信息,以及这些对象所依赖的table,index,view等对象的信息。
Library cache需要解决三个问题:
1.快速定位的问题:Library cache中对象众多,Oracle如何管理这些对象,以便服务进程可以迅速找到他们需要的信息。比如某个服务进程需要迅速定位某个SQL是否存在于Library cache中。
2.关系依赖的问题:Library cache中的对象存在复杂的依赖关系,当某个objec失效时,可以迅速将依赖其的对象也置为失效状态。比如某个表发生了结构变化,依赖其的SQL语句需要重新解析。
3.并发控制的问题:Library cache中必须有一个并发控制的机构,比如锁机制,来管理大量共享对象的并发访问和修改的问题,比如某个SQL在重新编译的同时,其所依赖的对象不能被修改。
Library cache结构:
Oracle利用hash table结构来解决library cache中快速定位的问题,hash table就是很多hash bucket组成的数组:
library_cache.jpg
原理与buffer cache中定位block的方式相同,将对象信息(比如SQL)hash定位到某个hash bucket中,然后顺序扫描bucket中的 List,实现快速定位对象的目的。Library cache handle是对象的一个指针,其中的namespace属性表示其指向的对象的类型:比如CRSR(Cursor),TABL(Table),INDX(Index) ,PROD(Procedure),TRIG(Trigger)等等。LCO(Library cache object)是handel指向的对象,包含了以下几个部分的内容:1.dependency table:指向本对象所依赖的对象,比如:select * from emp这个cursor的对象,依赖emp这个表,这里指向了emp这个表的handle。2.child table:指向本对象的子对象,比如某个游标的子游标。子游标是指SQL文本相同,但是SQL的实际含义不同的情况,比如执行的用户不同,执行计划不同,执行的环境不同等等,我们一般称之为SQL的不同版本。一个SQL至少包含一个父游标和一个子游标。3.authorization table:对象的授权信息。4.typeLibrary cache object的type,包括:shared cursor,index,table,cluster,view,synonym,sequence,procedure,function,package,table body,package body,trigger等等。5.data blocksdata block是一个指针,指向了data heap,即存放真实数据的地方,主要包括:diana tree, p-code, source code, shared cursor context area等等,如下图: library_cache2.jpg
Library cache对象依赖关系:对象依赖关系是利用LCO中的dependency table来完成的,我们设想以下的情况,用来说明对象间的依赖关系:两个共享游标:SQL1: select * from emp;SQL2: select * from emp和select a.name from emp a,dept b where a.dept_id=b.id and b.name=:1; library_cache3.jpg
SQL1产生了两个子游标,也就是SQL文本相同的两个不同版本,他们同时依赖emp表。SQL2只有一个版本,因为每个游标最少有一个子游标,所以它只有一个子游标,并且同时依赖dept表和emp表。Library cache中的并发控制:Oracle利用Library cache lock和Library cache pin来实现并发控制,Library cache lock是在handle上获取的,而Library cache pin则是在data heap上获取。访问对象时,首先必须获取handle上的lock,然后将访问的数据pin在内存中。lock的作用是控制进程间的并发访问,而pin的作用是保证数据一致性,防止数据在访问时被交换出去。Library cache lock有三种模式:null,share,exclusive,Library cache pin有两种模式:share,exclusive。下面详细解释在修改和访问对象时,lock和pin的作用:修改对象:编译SQL或PLSQL对象,获取该对象(cursor,procedure)handle上exclusive类型的lock,并且持有data heap上exclusive类型的pin,防止其他人读取和修改。同时,在该对象所依赖的对象(table)上,必须持有一个share类型的lock和pin,防止在修改的过程中,被其他进程所修改。访问对象:访问SQL或PLSQL对象,获取该对象(cursor,procedure)handle上NULL类型的lock,并且持有data heap上share类型的pin,同时,在其依赖的对象(table)上持有share类型的lock和pin。如果一个procedure依赖另外一个function,那么在被依赖的function上,也需要持有share类型的lock和pin。NULL类型的lock比较特殊,它只存在于cursor和procedure等只读对象上,它并不起到任何并发控制的作用,它更象是一个trigger,当对象失效时,通知所有访问这个cursor的进程。比如:select * from emp这个SQL,依赖emp表,当emp表发生变化时,cursor上的NULL lock被打破,所有有访问这个cursor的进程都会知道该对象已经失效。当持有对象的library cache pin时,会在row cache中对相应的对象加锁,就是row cache lock,阻止可能导致数据字典信息混乱的DDL发生。
library_cache4.jpg
lock和pin的实现类似于enqueue,在每个handle上都有lock和pin的holder list和waiter list,用来保存持有该资源和等待该资源的队列。阻塞分析:现实情况中,我们有一个数据库中存在被应用大量频繁访问的procedure,当依赖的表发生变更时,导致该procedure失效,这时会出现大量的library cache lock和library cache pin的等待,堵塞应用访问,造成了重大故障。出现这个问题的原因是:当procedure失效后,所有访问该对象的进程都尝试去编译,大量进程尝试获取exclusive类型的lock和pin,出现了大量的等待。后续的Oracle版本作出了改进,当出现这种情况时,只允许第一个进程尝试去编译该对象,编译通过后,所有的进程就可以并发访问,避免了大量进程同时尝试编译的情况出现。Library cache中的Latch:Library cache中相关的latch包括:shared pool latch,library cahce latch,library cache lock latch,library cache pin latch。Share pool latch的主要作用是分配或释放空间时使用,从Oracle9i开始,sharedpool被分成了很多个subpool,由多个shared pool latch保护,Oracle开始支持更大的shared pool。Library cache latch的主要作用是在hash bucket中定位handle时使用,library cache lock latch和library cache pin latch分别是获取lock和pin时,需要取得的latch。shared pool大小不合理,大量的硬解析以及SQL版本过多都可能导致shared pool latch和library cache latch的争用。从Oracle10g开始,Oracle正在逐步用mutex取代library cache中的latch,cursor:pin S和cursor:pin X相当于share和exclusive类型的library cache pin,cursor:pin S wait on X则表示share方式正在等待exclusive锁定。
标签: 暂无标签
oraunix

写了 199 篇文章,拥有财富 1026,被 339 人关注

转播转播 分享分享 分享淘帖
回复

使用道具

P4 | 发表于 2010-12-17 20:43:47
深度剖析啊。。。 学习
回复

使用道具

P4 | 发表于 2012-9-26 10:06:09
解析的很深刻,学习
回复

使用道具

P4 | 发表于 2012-9-27 11:07:40
仔细读完之后,颇有收获。但是有两点不太明白:
1)SQL1: select * from emp;SQL2: select * from emp和select a.name from emp a,dept b where a.dept_id=b.id and b.name=:1;SQL1产生了两个子游标,也就是SQL文本相同的两个不同版本,他们同时依赖emp表。SQL2只有一个版本,因为每个游标最少有一个子游标,所以它只有一个子游标,并且同时依赖dept表和emp表。

2)从Oracle10g开始,Oracle正在逐步用mutex取代library cache中的latch,cursor:pin S和cursor:pin X相当于share和exclusive类型的library cache pin,cursor:pin S wait on X则表示share方式正在等待exclusive锁定。(这段话完全读不明白。)

还相老师和各位指教。谢谢。
回复

使用道具

P4 | 发表于 2012-9-27 13:37:20
Library cache lock有三种模式:null,share,exclusive,Library cache pin有两种模式:share,exclusive。

其它有一些地方说:Library cache pin 也有三种模式:null,share,exclusive。
比如:http://www.eygle.com/archives/20 ... ache_pin_grant.html

到底该如何理解呢?

回复

使用道具

P4 | 发表于 2012-9-28 14:31:44
明白了 “cursor:pin S和cursor:pin X相当于share和exclusive类型的library cache pin,cursor:pin S wait on X则表示share方式正在等待exclusive锁定” 的含义:
cursor:pin S 相当于share类型的library cache pin
cursor:pin X 相当于exclusive类型的library cache pin,
cursor:pin S wait on X 则表示share方式的library cache pin正在等待exclusive锁定
回复

使用道具

P4 | 发表于 2012-10-2 11:03:00
Latches are the more restrictive mechanism, because they do not allow multiple
processes to inspect the protected data structure at the same time—they provide
for exclusive access only.[1] Locks allow for better concurrency, because they may
be held in a shared mode when the data structure is simply being inspected.
[1] This is a simplification. The redo copy latches can be shared, but this is hardware
dependent.
Another significant difference between locks and latches is request queuing.
Requests for locks are queued if necessary and serviced in order, whereas latches
do not support request queuing. If a request to get a latch fails because the latch
is busy, the process just continues to retry until it succeeds. So latch requests are
not necessarily serviced in order.
Because a latch can only be held by one process at a time, and because there is no
inherent concept of queuing, the latch data structure itself is very simple—
essentially just a single location in memory representing the state of the latch.
And because the latch data structure is so simple, the functions to get and release
a latch have very little work to do. By contrast, the data structures for locks are
much more sophisticated because of their support for queuing and concurrency.
So the functions to get, convert, and release locks have correspondingly more
work to do.
Of course, it is necessary for Oracle to ensure that only one process at a time can
modify the latch and lock data structures themselves. For latches this is easy.
Because each latch is just a single location in memory, Oracle is able to use the
TEST AND SET, LOAD AND CLEAR, or COMPARE AND SWAP instructions of
the underlying hardware's instruction set for its latch get operations. Because
these are simple machine instructions that are guaranteed to be atomic, no other
locking mechanism is needed. This simplicity makes latch gets very efficient.
Oracle's lock data structures, on the other hand, have several parts, and therefore
cannot be modified atomically. For this reason, Oracle actually protects operations
on locks with latches. The type of latch used varies depending on the type of lock.
For example, the cache buffer locks are indirectly protected by the cache buffers
chains latches, and the row cache enqueue locks are protected by the row cache
objects latch.
回复

使用道具

您需要登录后才可以回帖 登录 | 加入社区

本版积分规则

意见
反馈