今天来给大家分享一个Oracle使用中的小技巧。 当某条SQL语句或者对象被反复访问,过多的软解析可能会造成大量的“library cache:mutex X”争用,有什么样的方法处理此类问题呢?这是个头疼的问题。 今天的话题,就是介绍如何利用hotcopy来缓解library cache中的热点争用。在oracle 11g中,“library cache:mutex X”是个有点特殊的mutex,因为它存在于几个不同的位置,需要进一步的信息进行分辨。这里还会简单描述library cache的结构,理解library cache对认识oracle是非常重要的。

解决性能问题没有特别的方法,主要靠对数据库整体结构的准确理解。了解各种等待发生的原因,以及其在整个体系中的位置,才能做出正确的判断。 所以我会先大致介绍下10G和11G对library cache这个结构的保护方式。 这样你就会理解这个问题发生的可能原因。 然后,我们来尝试通过创建对象的hotcopy来缓解这类争用。

其中个别内容是我自己摸索和猜测出来的,难免有错误和不准确的地方,欢迎大家指正。

也许不是所有的同学都清楚library cache的结构,先在这里简单描述一下。

我们知道,当编译过的SQL已经存在于library cache中的时候,oracle会进行软解析,重用这个结构。 那么oracle如何知道是否已经存在可用的SQL呢? 是通过如图中的Hash结构。所有已经编译过的library cache object会被组织在一个hash结构中。 当进行搜索时, Oracle会对SQL语句进行hash计算,根据结果找到相应的hash bucket,比如bucket 6, 然后再搜索链接在这个bucket上的所有handle,这里你可以认为每个handle对应唯一的SQL文本。

一种情况,如果“Handle X” 正好是要找的SQL,则会向内搜索“Handle X”包含的child,寻找可用的cursor。 如果有完全符合条件的可用child,则重用,完成软解析。 如果没有,则创建一个新的child,完成一次硬解析。

另一种情况,如果没有找到符合条件的handle,说明SQL 文本是新的,则需要创建一个新的handle和第一个child。 同样完成一次硬解析。

那么为什么要在这个结构上进行锁保护呢?什么操作需要加锁?

一个很简单的例子,如果没有锁的话,假设process 1和process 2同时执行同一个SQL,当他们都没有找到匹配的Handle时,有可能重复添加针对同一SQL的Handle Y。

同样的,当两个进程同时搜索Handle X下是否有匹配的Child时,也有可能在此Handle下,添加两个相同的Child。

因此,为了避免这种情况发生,对此结构的锁是必要地。 由于这些操作都是快速的内存操作,此类锁不宜采用复杂的结构,没有共享模式和独占模式之分。 所以,只有一个进程可以对某个结构进行搜索和修改。也就是说,即使是软解析,在结构内进行搜索时,也是串行的。

在10g和11g,library cache锁的粒度是不同的。

10G的时候,保护这个结构的是 latch: library cache。 这个latch的默认数量为大于CPU Count的最小质数,而默认最小的bucket个数为509,这就意味着每个latch要保护多个Hash Buckets以及相应的handle。 也就是说,对于一组bucket和handle,每次只有一个进程可以搜索修改。因此,这个latch经常成为热点。

11G以后,此latch被替换为library cache: mutex X。锁的粒度变小,每个bucket和每个handle都被一个单独的mutex保护,大幅度减小了争用

然而,从latch名字本身,我们区分不出等待是发生在hash bucket上,还是handle上。需要通过p1来进行分辨。

如果P1是bucket的编号,通常比较小。 如果下面查询返回结果,说明争用发生在hash bucket上。 返回结果为链接在此bucket上的对象。

select KGLNAHSH, substr(KGLNAOBJ, 1, 30) Name,

KGLHDNSP Namespace, KGLNAHSV Hash

from x$kglob where KGLHDBID = &p1;

这种情况下,锁是在bucket上,即对handle进行访问操作时发生的。

实际上,这种情况并不常见,因为每个bucket上链接到的handle通常不会很多。 为了提高hash表的效率,当bucket上平均handle数量超过2时,oracle会将bucket的个数翻倍,重建hash表,用空间交换时间。 在链不长的情况下,一般handle上会先遇到瓶颈。

更常见的争用位置,是在 handle上,这说明某个特定cursor或者object被搜索时发生争用。

如果下面查询返回结果,则说明是这种等待。返回结果为handle所对应的对象。 可能是cursor,也可能是object

select kglnaown, kglnaobj

from x$kglob

where kglnahsh = &p1;

明白了大致的原理之后,就可以想象到这个mutex争用的可能原因。

首先,它有可能是硬解析造成的。 当发生硬解析时,无论要创建一个新的handle,还是要创建一个新的Child,都需要额外大量的时间来完成,相应地,对这个mutex的持有时间会明显变长,造成争用。

由于硬解析会向shared pool申请大量的内存,因此这种情况会伴随一系列其他等待如 latch: shared pool, library cache load lock。 解决办法就是分析硬解析过多,或者version count过高的问题。

还有一种情况,就是OS资源不足,特别是CPU资源紧张。 这种情况下,oracle进程无法获取足够的资源去完成相应的工作,无法及时释放此mutex,造成请求的堆积。

再有,就是某个持有者长时间不释放此mutex,造成请求的积压。这是不正常的, 需要对mutex持有者的当前状态进行分析。 Errorstack, process dump。 如果持有者被其他进程阻塞,则通过hanganalyze等工具继续查找最终持有者。

另外,个别Oracle bug也会造成此类问题。

如果,以上原因都被排除掉,那么,对某热点SQL或热点object的频繁访问,也会造成此问题。 也就是我们之前说过的,哪怕是软解析,也会在查找library cache结构的时候串行。 这类问题比较让人头疼,一方面,SQL语句来自业务,我们不能人为减少SQL的执行次数和效率。 另一方面,如果SQL的文本相同,就一定会被hash到一个特定的handle上,这个是无法改变的。从前遇到这类问题非常让人头疼,一般可能的解决办法见下一页。

那么接下来该怎么办呢?

首先,可以查下是否有连接风暴。 连接风暴可能造成某些PLSQL对象的频繁执行,是造成此类问题的常见原因之一。

Version count如果很高,也会引发这个问题,因为找到handle以后, 对child的搜索是用遍历的方式,如果version很高child很多,则每次搜索的时间很可能会变长。会造成对handle上的锁,持有的时间也变长。所以,这也是一个可能的原因。

另外,和开发联系,研究SQL或某个对象如此高的并发是否正常的。 如果SQL来自不同的模块,则可以试着修改来自不同位置的SQL文本(比如加空格,或无用注释),使他们hash到不同的handle上。

增加session_cache_cursors是个可能的尝试,如果cursor被cache住,child的位置会被保存在pga中,那么查找child的速度会明显加快,对Mutex的持有时间也会变小。

如果以上方法均不适用,我们最后可以尝试创建hotcopy来改善此问题。

对于资源争用的问题,解决办法只有两个,要么减小需求,要么增加资源数量。而hotcopy的原理,实际就是在hash SQL文本的时候,加上PID的部分。 这样,哪怕执行相同的SQL文本,不同进程就有可能会被hash到不同的handle上。 这实际增加了资源的数量。当然,copy的数量是可控的。

制作了hotcopy以后,相同的对象和child可能多次出现在library cache的不同位置,造成了一部分空间浪费,但却可以解决library cache中热点对象或热点cursor的争用。也是一种用空间换时间的办法。

hotcopy这个功能是通过fix 9239863和fix 9282521引入的。 11.2.0.2以上版本可以直接使用。 低版本数据库需要安装相应地补丁。 针对11.2之前版本的数据库,需要设置两个隐含参数。 slide里有详细的描述。针对cursor 和 object对应不同的方法。

11.2之后,可以通过标准API进行设置。

http://docs.oracle.com/cd/E11882_01/appdev.112/e40758/d_shared_pool.htm#ARPLS68085

下面我们用一个简单的实验,查看到底发生了什么。 在试验中,我模拟了一个场景,大量session反复执行某一个SQL。

从查询结果来看,内存中ASH捕捉到的等待事件, library cache: mutex X 占据了很高的比例。

AWR报告反应了类似的内容。等待进入了top 1。

经查询,library cache: mutex X等待的P1非常集中。

经过验证,P1的值指向该条cursor的handle。 其实你看这个数字的长度,就知道不可能是hash bucket。 这个handle所在的bucket是14503。

接下来, 我们用之前介绍的方法来激活基于此cursor的hotcopy。

由于我的实验机器CPU太少,所以 我提前设置了隐含参数”_kgl_hot_object_copies”=4来指定copy的个数。

在这里我们使用了11.2提供的API进行hotcopy的实施,针对cursor,需要完整的hash,可以从X$KGLOB.KGLNAHSV中获取。

然后再次提交同样的负载。

这一次,我们看到,ASH捕捉到的mutex等待开始分散到多个P1上,总数量在变少(忽略32127143,这是第一次试验遗留的结果)。 通过进一步验证能够确认,每个handle的内容都是这个cursor。

这里我也注意到14503这个hash bucket上的争用增加,如果你还记得之前的输出,这其实是修改前那个cursor所在的hash bucket。 我猜测即使做了hotcopy,请求仍旧会经由这个bucket跳转。由于handle上的请求处理速度变快了, bucket上的争用开始显现,从library cache的结构来看,这些是合理的。

从library cache dump 中验证,的确增加额外4个handle,相同的对象名。

在新生成的AWR报告中, library cache: mutex X 等待时间下降了50%, 从1882秒,下降到942秒.  由此可以验证,针对纯粹的library cache的热点争用,hotcopy是可以进行缓解的。

最后做一个简单地小结。

首先,从library cache的结构看, 即使是软解析,对child和handle的搜索,也是串行的。 虽然这个操作速度很快,但仍会造成热点争用。

另外,造成library cache: mutex X争用的原因很多,只有纯粹的热点争用才需要用hotcopy来解决。

最后,以我的经验来看,解决数据库性能问题,没有固定的套路。 Oracle是个极其庞大复杂的体系,几乎不可能通过几个简单的等待事件推测出根本原因,不会有这样的“神”。 正确的分析方法是,尽可能多的收集证据,然后利用自己的知识和对整体结构的理解,推导出一个“故事”把所有证据串联起来,有了“故事”以后,再收集更多的证据,反过来来验证故事的正确性。

Oracle后台专家解决library cache锁争用的终极武器相关推荐

  1. oracle 存储过程挂起,library cache pin与PROCEDURE的重建

    library cache pin与PROCEDURE的重建 前面提到,Oracle10g重建Procedure的处理有所增强,最初看到这个增强的时候,我想这个增强是否可以减少困扰已久的Library ...

  2. oracle package lock,Oracle 11g下重现library cache lock等待事件

    从下面的例子中可以看到,在生产数据库中对象的重新编译会导致library cache lock,所以应该尽量避免在业务高峰期编译对象.如果是package或过程中存在复杂的依赖关系就极易导致libra ...

  3. 周三直播丨Oracle 12cR2 ADG LGWR Library Cache案例分享

    Active DataGuard上的library cache lock案例,应该算是Oracle 11g 版本上常见的经典BUG,Oracle也相继给出了几个隐含参数和补丁修复解决方案,但为何打了补 ...

  4. 直播丨Oracle 12cR2 ADG LGWR Library Cache案例分享

    Active DataGuard上的library cache lock案例,应该算是Oracle 11g 版本上常见的经典BUG,Oracle也相继给出了几个隐含参数和补丁修复解决方案,但为何打了补 ...

  5. 《Oracle高性能自动化运维》一一2.3 Library Cache

    本节书摘来自华章计算机<Oracle高性能自动化运维>一书中的第2章,第2.3节,作者:冷菠 著,更多章节内容可以访问云栖社区"华章计算机"公众号查看. 2.3 Lib ...

  6. 隐含参数与 Library Cache 与 Shared Pool Latch 原理

    现在每一个 Oracle DBA,很少有不知道隐含参数的.但至少在表面上,Oracle 是不支持将隐含参数用于数据库的.隐含参数通常用于救急,或者是作为 Oracle BUG 的临时解决方案(Work ...

  7. (转载)library cache lock和library cache pin到底是什么

    (http://www.dbsnake.net/library-cache-lock-and-pin.html) Posted: December 16, 2011 | Author: Cui Hua ...

  8. oracle library cache lock,【DB】彻底搞清楚library cache lock的成因和解决方法(一)

    问题描述: 接到应用人员的报告,说是在任何对表CSNOZ629926699966的操作都会hang,包括desc CSNOZ629926699966,例如: > sqlplus SQL*Plus ...

  9. oracle library cache lock,【案例】Oracle等待事件library cache lock产生原因和解决办法...

    [案例]Oracle等待事件library cache lock产生原因和解决办法 时间:2016-12-07 18:56   来源:Oracle研究中心   作者:网络   点击: 次 天萃荷净 O ...

最新文章

  1. pyqt5实战之幻彩大蛇(贪吃蛇)-1
  2. 页面重新跳转到父类url
  3. java 循环关键字_Java循环结构_常量_关键字
  4. 上阿坤的课程的注意事项
  5. iframe子页面与父页面元素的访问以及js变量的访问[zhuan]
  6. 成像数据更好的展示_为什么更多的数据并不总是更好
  7. 查一个字段中字符集超过30的列_详细解读MySQL的30条军规
  8. C/C++求一个整数的二进制中1的个数
  9. CvArr、Mat、CvMat、IplImage、BYTE转换
  10. feature scaling小结
  11. 阿里云存储:安防行业背后的赋能者 | 凌云时刻
  12. qq手机助手连接服务器失败是什么原因,按键精灵手机助手教程,按键精灵手机助手连不上手机解决方法...
  13. TTF、TOF、WOFF 和 WOFF2 的相关概念
  14. 腾讯新游侍魂上线,侍魂:胧月传说安卓模拟器电脑版详细教程
  15. 地理空间索引实现:z 曲线、希尔伯特曲线、四叉树, 最邻近几何特征查询、范围查询
  16. Word交叉输入汉字和英文间距变大
  17. 淘宝url中的spm编码是怎么生成的呢?
  18. iOS通过dSYM文件分析crash
  19. input框5连--输入框不可输入以0开头的数字但是可以输入带0的数字常用正则
  20. centeros 7 安装kafka

热门文章

  1. IOT专用IOP平台
  2. 2021秋招复盘【基础版】
  3. MATLAB打开nc文件并读取nc文件数据
  4. The 2020 ICPC Asia Yinchuan Regional Programming Contest 银川 B. The Great Wall 题解
  5. 【k8s金牌知识】k8s升级攻略
  6. 对C/C++中的void与 void*认识
  7. 突发!爱奇艺崩了!小米电视崩了,韩剧TV也崩了?爱奇艺回应:正全力解决...
  8. 《Java语言程序设计与数据结构》编程练习答案(第四章)(一)
  9. 读书笔记 - 《战天京》
  10. Proxy与Reflect详解