Library cache内部机制详解II

3 1st, 2011 | Posted by jacky | Filed under 大话技术

我之前曾经写过一篇Library cache内部机制详解,但是遗留了一些关于11g中mutex的改进的问题,最近因为有些11g的数据库频频发生mutex相关的等待事件,所以我又多这个问题做了一些探讨。

关于Mutex,可以参考ORACLE mutex实现机制这篇文章,mutex是从10g开始引入的,在library cache中有大量的使用,它的主要作用有两个:一是用来替换library cache pin,二是作为更轻量级的latch使用。

在9i中,Library cache lock有null,share,exclusive三种模式,lock的作用是控制进程间的并发访问。Library cache pin有share和exclusive两种模式,pin的作用是保证数据一致性,防止数据在访问时被交换出去。我们先来回顾一下library cache lock和library cache pin在不同场景下的使用方式:

Procedure/function/trigger

访问对象:需要在object handle上获取一个null类型的library cache lock(首先获取share,然后转换为null),然后在data heap上获取share类型的library cache pin,在其所依赖的表上不加任何lock和pin(先申请share类型的lock,申请到之后不再持有任何lock和pin,允许修改procedure所依赖的对象,即允许被打破)。

编译对象:需要在object handle上获取一个exclusive类型的library cache lock,然后在data heap上获取exclusive类型的library cache pin,同时在依赖的对象上获取share类型的library cache lock和pin,保证依赖的对象不能被修改。

当持有对象的library cache pin时,同时会在row cache中对相应的对象加锁,就是row cache lock,阻止可能导致数据字典信息混乱的DDL发生,row cache lock和library cache lock/pin一样,都是为了保证对象的一致性。

Cursor

Cursor execute:在object handle上获取null类型的library cache lock(首先获取share,然后转换为null),然后再data heap上获取share类型的library cache pin,在其所依赖的表上不加任何lock和pin(先申请share类型的lock,申请到之后不再持有任何lock和pin,允许修改cursor所依赖的对象,即允许被打破)。

Cursor hard parse:Cursor硬解析需要在object handle上获取exclusvie类型的library cache lock,然后再data heap上exclusive获取类型的library cache pin,同时在依赖的对象上获取share类型的library cache lock和pin,保证依赖的对象不能被修改。

Null类型的library cache lock与share类型的最大区别在于,Null lock并不起到并发控制的作用,它仅仅类似于一个触发器,当cursor所依赖的对象被修改时,需要获取exclusive类型的library cache lock/pin,这时Null lock被打破,Null lock会通知所有访问该对象的进程,表明cursor已经处于失效状态,需要重新解析,所以这种锁又称为“breakable parse lock”。

从上面的分析看出,Cursor和procedure需要获取的lock和pin是一致的。

Oracle 11g的变化

Oracle从10g开始在library cache中引入mutex,在11g中mutex得到了更大规模的使用,主要有以下几个等待事件:

cursor: pin X
cursor: pin S
cursor: pin S wait on X
cursor: mutex X
cursor: mutex S
library cache: mutex X
library cache: mutex S

cursor: pin S,cursor: pin X,cursor: pin S wait on X这三个等待事件,实际上就是替代了cursor的library cache pin,pin S代表执行(share pin),pin X代表解析(exclusive pin),pin X wait on X代表执行正在等待解析操作。这里需要强调一下,它们只是替换了访问cursor的library cache pin,而对于访问procedure这种实体对象,依然是传统的library cache pin。

cursor: mutex S,cursor: mutex X这两个等待也与cursor有关,一些资料上的解释是:cursor: mutex S用于Examining parent cursor, Querying V$SQLSTATS bucket,cursor: mutex X用于Loading new child cursor under parent, Modifying V$SQLSTATS bucket,Updating bind capture data。关于这两个等待的使用场景,目前还不是特别明确,我猜测它们是cursor: pin S,cursor: pin X这两个等待需要获取mutex时的产生的等待,因为cursor pin也是通过mutex实现的。

从上面的分析我们看出,在11g版本中,library cache lock和library cache pin依然存在,Procedure和function等对象仍旧使用原有的方式,Null类型的library cache lock也依然存在,作用同样是在依赖对象改变时,通知失效的cursor,唯一的变化是cursor的library cache pin被mutex的相关等待所取代。

library cache: mutex X,library cache: mutex S,这两个事件很明显是用来替代之前的library cache latch,主要作用是在hash bucket中定位handle时使用。而share pool latch和library cache load lock latch,latch依然存在,估计后续版本可能会逐步被替换掉。

–EOF–

附:9i,10g,11g关于library cache的等待事件比较,从中我们可以看到各版本的变化。

Wait event

Latch

9i

library cache pin

library cache lock

library cache load lock

shared pool

library cache

library cache pin

library cache pin allocation

library cache load lock

10g

cursor: mutex X

cursor: mutex S

cursor: pin S wait on X

library cache pin

library cache lock

library cache load lock

cursor: pin X

cursor: pin S

library cache revalidation

library cache shutdown

library cache

library cache lock

library cache pin

library cache pin allocation

library cache lock allocation

library cache load lock

library cache hash chains

11g

cursor: mutex X

cursor: mutex S

cursor: pin S wait on X

library cache pin

library cache lock

library cache load lock

library cache: mutex X

library cache: mutex S

cursor: pin X

cursor: pin S

library cache revalidation

library cache shutdown

library cache load lock

shared pool

标签:
  1. 木匠Charlie
    3 2nd, 201107:32

    解释的简洁明了.

  2. jacky
    3 2nd, 201110:28

    @木匠Charlie
    能得到您老的肯定,我非常滴开心。

  3. 木匠Charlie
    3 2nd, 201113:38

    你修炼的境界又提高了, 鼓掌.

    http://twitter.com/#!/mujiang/status/42820721705091072

  4. 木匠Charlie
    3 2nd, 201113:40

    坏了. 听Eygle讲, 留下 twitter 的印迹, 是会被封掉网站的, 赶紧把鄙人的上一条留言删除了吧.

  5. jacky
    3 2nd, 201113:40

    @木匠Charlie
    未来ORACLE internal会越写越少,更多偏向于解决方案。

  6. jacky
    3 2nd, 201113:41

    @木匠Charlie
    封就封了吧,我的twitter还同步在首页上呢。

  7. 木匠Charlie
    3 2nd, 201113:52

    我是指你处理人际关系的境界, 有高度. ^_^ . “谦虚谨慎,有容乃大”.

  8. jacky
    3 2nd, 201114:20

    @木匠Charlie
    惭愧啊,我总是在反思自己在处理人际关系方面不够成熟。

  9. jacky
    3 3rd, 201117:18

    @木匠Charlie
    今天听了同事的分享,发现有一些错误,做了如下更正:第一,cursor和procedure获取lock和pin是一致的,都可以被打破,执行时先获取share,然后转换为null。

  10. jacky
    3 3rd, 201117:36

    @木匠Charlie
    另外一个错误,执行cursor和procedure时,所依赖的对象上都不需要任何lock和pin。

  11. 木匠Charlie
    3 4th, 201104:10

    对的是跟你学的,错的也是跟你学的. 这个原理差不多了解就行了, 目的是自己说服自己,讲一个前后圆满的故事.

    更正改到正文里面好一些,方便后来者.

  12. jacky
    3 7th, 201109:44

    @木匠Charlie
    正文已经更正了。

  13. Meets
    11 2nd, 201113:19

    昨天进行一个 dbms_redefinition.finish_redef_table 出现了Library cache lock 的等待,随后引起了一系列的cursor pin s wait X 的等待事件。 当时情况比较紧急,直接给在线重定义 abort 了。 没有找到root cause。lock 的对象就是要finish 的表。

    什么情况会导致对这个表的library cache lock 长期持有呢?至少是shared 模式。