Oracle Shared Pool机制之——Latches, Locks, Pins and Mutexes
本文中,我们将讨论共享池(Shared Pool)中的各种内存保护结构,即Latches,Locks,Pins和Mutexes。
1. Lathes
当在库缓冲(Libraray Cache)中创建新对象而没有足够的自由内存(没有足够大的单个自由内存块(Chunk of Free Memory))时,Oracle就会用LRU算法从相应哈希链表上分离(Delink)已有对象,并将新对象加入哈希链表上,该过程中,都会涉及各个对象中前后地址指针的修改,也会涉及各对象在自由链表及库缓冲链表间的移动。
如上场景中,Latches将派上用场。Latches是保护系统全局区中共享数据结构的简单、低级的串行机制。Latches消除了多进程同时修改共享内存时面临的冲突问题。当服务器或后台进程操作或访问这些共享数据结构时,将会在很短时间内获取Latches。
共享池Latches用于保护和获取共享池的并发访问。一个Latch可以覆盖多个哈希桶(Hash Buckets),因此,一个进程在哈希桶中搜索某个对象前,必须先获取保护该哈希桶的Latch,然后,搜索整个哈希桶链表,完成需要的所有处理和操作后,再释放该哈希桶上的Latch。如果此时另一个用户也想搜索同一个Latch下的某个哈希桶链表,那么,就必须等待前面的用户释放覆盖该哈希桶链表的那个Latch,这就导致了Latch冲突。
2. Latches冲突——Locks和Pins
当Latch被长久持有或Latch需求太高时,就会产生Latch冲突。影响Latch
冲突的因素主要有三个。
1) 覆盖整个库缓冲的Latches数。如果Latches数较多,那么,每个Latch保护的哈希桶数就会更少,当你需要搜索某个哈希桶链表时与其他使用相同Latch的用户发生冲突的几率就会少;另一方面,如果系统中有更多的Latches,那么,系统将会有更多的维护、报告或清理任务要做。
共享池架构中,有固定数目的库缓冲Latches保护固定数目的哈希桶,当然,也会按需增长。
直到Oracle 10g版本,覆盖库缓冲的Latches数都非常少。该数目依赖于系统上的CPUs数,应该是与cpu_count参数值相当在,直至最大达到67个Latches。这个数目出奇的小,以至于,即使在系统上运行少量而频繁执行的不通过语句,即使存取不同的哈希桶,但可能因为获取相同Latch而发生Latches冲突。
2) 需要获取特定Latches的次数。用户获取特定Latch并遍历相应链表的次数越多,与其他获取同样Latches的其他用户产生冲突的可能性就越大。
一旦发现某个对象,我们可以给该对象附加一个KGL Locks(kgllock),从而使得对库缓冲的搜索次数最小化,这样,我们就拥有一个到该对象的捷径(当打开/关闭游标时存储于PGA中)。当下次同样的语句发布时,我们就可以在PGA中找到该对象而不必再搜索相应的哈希桶链表(软软解析)。
3) 必须持有Latch的时长。大家持有Latch的时间越长,那么,与其他持有该Latch的其他人产生冲突的可能性就越大。
我们应该避免长时间持有Latches。这就意味着当我们对已发现的某个内存区域做一些耗时处理时,可以将该对象Pin住,以保护我们正使用的内存区域,从而我们能释放相关Latch。
因此,服务进程发现相应哈希桶后,随后的步骤如下所示。
a) 获取覆盖相应哈希桶的Latch;
b) 获取特定对象上的Lock以便将指向该对象的指针放入PGA中(当打开游标时);
c) 将该对象Pin住并释放相应Latch;
d) 完成特定对象上的所有处理和操作(例如:执行语句/过程);
e) 获相应Latch,Unpin该对象并释放相应Latch;
除非发生修改,否则,Locks和Pins通常处于共享模式。
3. Lirary Cache Locks(KGL Locks) 如何被获取?
可以通过三种主要方式可以获取KGL Locks:
1) 用户可以写前端代码来持有频繁使用的游标;
2) 用户可以设置session_cached_cursors参数,以使得Oracle看到用户使用一条语句多于两次时,库缓冲将自动持有相关游标;
3) 用户将得益于PL/SQL调用中打开(显式或隐式)的游标将被持有的半自动方式,该功能在Oracle 9.2.0.5以上版本中被支持。该特性也将通过session_cached_cursors参数设置进行控制。当代码不显式持有游标时,该参数设置将被持有的游标数,该参数也控制持有会话运行PL/SQL代码打开的游标数。
4. KGL Locks的好处
除了最小化我们搜索对象时对库缓冲的检索次数外,该Locks还提供如下好处:
1)通过Locks方式,一个用户可以阻止其他用户存取相同的对象。库缓冲Locks用对象句柄作为资源结构,且获取该资源上的Locks。如果资源处于不兼容模式而不可用,则会话必须等待库缓冲对象变为可用。
2)也被称为解析(Parse)Locks的库缓冲Locks用于维护对象及其依赖对象的依赖机制。
5. 为什么需要库缓冲Pins(KGL Pins)?
当一个对象被实际使用时,KGL Pin才会发挥作用。虽然KGL Locks将持有内存中的对象(PGA中的游标指向共享池中的对象),但如果系统上内存压力较大,对象的某些动态创建部分(例如:SQL语句的执行计划)也将会被移出内存。然而,当一个对象被实际使用时,必须确保其可重建部分不能被移出内存,因此,为了确保这点,需要将这些对象Pin住。
Pin住对象会导致其相关堆被加载进内存。如果一个用户想修改或检查该对象,则必须获取Lock后再获取Pin。
如果一个用户想修改库缓冲对象依赖的底层对象,则需要首先以独占模式获取该底层对象上的库缓冲Pin。如果依赖库缓冲对象(例如:SQL语句)正在执行,则这些Pins将因为不可用而发生等待。因此,库缓冲对象上的解析Locks被破坏前,独占模式的库缓冲Pins必须首先被获取,以便对库缓冲对象进行更改。
库缓冲对象上Locks及Pins的相关信息可通过三个X$表进行查询,即x$kgllk, x$kglpn和x$kglob.
1)x$kgllk包含一个对象上的所有Locks结构;
2)x$kglob包含Locks资源项;
3)x$kglpn 包含所有的库缓冲Pins。
6. KGL Locks及Pins相关问题
库缓冲锁及钉住(Locking和Pinning)机制也许会导致两个问题。
KGL Locks及Pins本身只是小内存区域,根据需求同时被分别创建和废弃,并从共享池分配内存。因为KGL Locks大约占用200个字节,而KGL Pin大约占用40个字节,因为相关它们的内存经常分配和释放,导致共享池出现蜂窝状的自由内存,即自有内存总数很多,但没有连续的大内存块。因为库缓冲Pins来去很快而非常讨厌,KGL Locks则因为能和对象存在一段时间而不是那么太糟糕。
KGL Locks及Pins相关的另一个问题是,当使用它们时,必须频繁的创建内存区域,标明属性,将它们插入链表(或移出链表并将其放回共享池),期间,这些操作需要一直持有独占模式的Latch,对繁忙的系统来说,整个库缓冲Locks及Pins将带来很大威胁。
Oracle10g版本中,Oracle公司引进了库缓冲Lock Latch和库缓冲Pin Latch,这将允许对相同Latch覆盖的不同哈希桶进行某些并发操作。然而,当我们升级到Oracle 11版本时,整个KGL Lock及Pin机制逐渐被Mutex机制替代。
7. Mutexes
为了改善游标的执行和硬解析,Oracle 10gR2版本引入了一个新的、更好粒度的内存串行机制。对某些共享游标相关的操作,Mutexes(Mutual exclusion objects,互斥对象)可用来替代库缓冲Latches和库缓冲Pins。Mutex工作方式与Latch基本相同,但操作Mutexes的代码路径更短,更轻量级,通常也会被硬件直接支持。因此,与Latch机制相比,Mutexes会更快,耗费更少的CPU,并发性方面也会有很大提升。32位Linux系统上,常规Latch结构占用110字节,而Mutex仅占28字节。而Mutex消耗的指令也更少。获取一个Latch需要消耗150~200个指令,而获取一个Mutex则只需大约30-35个指令。
因为Mutex提供较少关于谁正等待什么及等待时长等信息,所以,Mutex结构较小。你可以获取Mutex睡眠次数的信息,但不能获取需求次数及命中失败次数。
8. Mutex的好处
Mutexes可以共享或独占模式获取,也可以等待或非等待模式完成。
1)Mutexes不太容易发生假性冲突。前面提到,多个哈希桶可能在同一个Latch覆盖之下。而两个用户搜索同一Latch覆盖下的两个不同哈希桶容易发生假性冲突。即因保护机制(Latch)而非用户正存取的目标对象而发生的冲突。不像Latches,Mutexes可能会为每个被保护对象创建一个Mutex。这样,因为每个被保护的结构都有一个自己的Mutex,这就意味着发生假性冲突的可能性要低得多。目前,父子游标都有自己的Mutex,用户不必为了争夺被多个游标共用的一个Latch而发生冲突。
2)替换Latches和Pins:Mutexes具有双重性。其可以作为一种串行机制(像一个Latch),同时也可以作为一个Pin(例如:阻止对象从内存中被移除)。 一个Latch不能被多个会话同时获取,而一个Mutex可以被多个会话同时参考,多个会话可以共享模式参考该Mutex。以共享模式参考一个Mutex的总会话数被称为参考数(Ref Count)。一个Mutex的参考数被存储于其自身。一个Mutex也可以独占模式被一个会话持有。
一个Mutex的参考数是对一个库缓冲Pin的替代。当使用Latches时,任何时候每个会话执行一个语句时,它首先重建并接着删除一个库缓冲Pin,而使用Mutex时,每个会话只需增加和减少相关Mutex的参考数即可(因此,参考数可替代n个不同的Pins)。这意味着在一个对象相关Mutex的参考数降为零之前,即该对象目前未被任何用户存取,该对象不能被从内存中移除。3)Mutex结构位于每个子游标句柄中,且其本身作为该游标的Pin结构。为了改变游标的Pin状态,之前我们需要获取库缓冲Latch,但现在我们可以直接修改游标Mutex的参考数。
除了每个子游标句柄中有Mutex结构且其作为游标Pin结构而带来的主要好处。如果你正有一个游标被打开(或在会话游标缓冲内),你不必获取库缓冲Latch(而之前为了改变游标Pin状态而必须这么做),就可以直接修改游标Mutex的参考数(通过会话UGA内打开游标状态区域的指针)。
所以,当钉住和释放(Pinning/unpinning)游标且无需分配和维护单独的Pin结构时,将会获得极高的可扩展性。
9. 相关注意事项
1) 库缓冲Latch机制在解析等操作中依然被需要,Mutexes仅仅解决了库缓冲的Pin问题。
2) Mutexes目前被用于库缓冲游标(而非其他类似PL/SQL存储过程,表定义等)。
3)由于Mutexes是一种通用机制(而非库缓冲专用),其也被用于V$SQLSTATS底层结构。
4)当Mutexes被开启时,从X$KGLPN中将不再能看到游标Pins(由于X$KGLPN是一个基于KGL Pin数组的固定表——其将不再被用于游标)。
5)Latches和Mutexes为独立的机制,即一个进程可以同时持有Latch和Mutex。Oracle10.2.0.2以上的版本中,只要“_kks_use_mutex_pin”参数被开启,库缓冲Pin Latch将被Mutex替代,同时,其他一些类似V$SQLSTATS数组及父游标检查的操作也被Mutexes保护。然而,使用kksfbc()的真正子游标查找依然被库缓冲Latches保护,但是,频繁软解析加上很少的游标缓冲及较长的库缓冲哈希链将导致这些Latches成为一个问题(记住,即使在普通的哈希链扫描中,库缓冲Latch始终被以独占方式获取)。
Oracle 10g中,你将看到三种类型的Muxtes被使用,分别为Cursor Stat,Cursor Parent,Cursor Pin。因此,Oracle 11.2版本中去掉了所有内存和链表的小区域,事实上,该版本甚至去掉了用于保护哈希链的Latches,而代之以Mutexes。每个哈希桶被一个Mutex保护。如果在哈希桶上采用Mutexes,那就是用每个桶上一个Micro-Latch代替了最大用67个Latches覆盖131072个桶。如果在每个库缓冲对象上用一个Mutex来代表KGL Locks,而用另一个来代表KGL Pins,那将不必做所有的内存分配和释放,也不必运行代码来进行连接链表的操作。因此,从Oracle 11g版本开始,每个库缓冲桶由一个独立的Mutex来保护(对,总共131072)。
Oracle 11g版本中,有另外一些Mutexes,其中最重要的一个是库缓冲Mutex。同时,除了“library cache load lock”外,所有库缓冲相关的Latches都消失了,取而代之,相应操作都被Mutexes保护。“libarary cache”Latches已被“library cache”Mutexes替代。
下列出现于Oracle 10g版本的Latches在Oracle 11g中已不复存在:
librarycache pin allocation
librarycache lock allocation
librarycache hash chains
librarycache lock
librarycache
librarycache pin
而Oracle 11g版本中仅剩的Latches为:
librarycache load lock
下列出现于Oracle 10g版本的与库缓冲相关的等待事件在Oracle 11g版本中也不复存在:
latch:library cache
latch:library cache lock
latch:library cache pin
Oracle 11g版本中与库缓冲相关的等待事件为:
librarycache pin
librarycache lock
librarycache load lock
librarycache: mutex X
librarycache: mutex S
OSD IPClibrary
librarycache revalidation
librarycache shutdown
当然,库缓冲Mutexes还并不能解决这个世界的所有问题(特别是与过度硬解析相关的问题),例如:两个完全不同的游标依然有可能发生哈希冲突。如果一个父游标下有多个子游标,而应用疏于游标管理(例如:每次执行后关闭游标,而没有做会话游标缓冲),那么,由于连续的游标哈希链遍历而可能发生Mutex冲突。
Oracle Shared Pool机制之——Latches, Locks, Pins and Mutexes的更多相关文章
- Oracle Shared Pool 原理
Oracle Shared Pool 原理 由于shared pool中最重要的是library cache,所以本文主要讲解Library cache的结构,library cache latch, ...
- Oracle Shared Pool之Library Cache
1. Shared Pool组成 Shared Pool由许多区间(Extent)组成,这些区间又由多个连续的内存块(Chunk)组成,这些内存块大小不一.从逻辑功能角度,Shared pool主要包 ...
- Oracle-buffer cache、shared pool
http://blog.csdn.net/panfelix/article/details/38347059 buffer pool 和shared pool 详解 http://blog.csd ...
- Oracle数据库体系结构-Shared Pool
Oracle数据库简单介绍 对象关系型数据库 重点:一致性+性能 一致性优于性能 处理模型:C/S模型 Client:用户和用户进程 Server:服务器进程,实例,数据库本身 ...
- Oracle数据库案例整理-Oracle系统执行时故障-Shared Pool内存不足导致数据库响应缓慢
1.1 现象描写叙述 数据库节点响应缓慢,部分用户业务受到影响. 查看数据库告警日志,開始显示ORA-07445错误,然后是大量的ORA-04031错误和ORA-00600错误. 检查数据 ...
- Oracle数据库大量library cache: mutex X及latch: shared pool问题排查一例
业务系统数据库夯住,数据库内大量的library cache: mutex X及latch: shared pool等待,alert日志信息如下 Tue Sep :: WARNING: inbound ...
- 深入浅出Oracle学习笔记:Buffer Cache 和Shared pool
Buffer cache 和 share pool 是sga中最重要最复杂的部分. 一.Buffer Cache 通常数据的读取.修改都是通过buffer cache 来完成的.buffer cach ...
- [转载】——故障排除:Shared Pool优化和Library Cache Latch冲突优化 (文档 ID 1523934.1)
原文链接:https://support.oracle.com/epmos/faces/DocumentDisplay?_adf.ctrlstate=23w4l35u5_4&id=152393 ...
- Oracle Redo Log 机制 小结(转载)
Oracle 的Redo 机制DB的一个重要机制,理解这个机制对DBA来说也是非常重要,之前的Blog里也林林散散的写了一些,前些日子看老白日记里也有说明,所以结合老白日记里的内容,对oracle 的 ...
随机推荐
- NPOI 导入Excel和读取Excel
1.整个Excel表格叫做工作表:WorkBook(工作薄),包含的叫页(工作表):Sheet:行:Row:单元格Cell. 2.NPOI是POI的C#版本,NPOI的行和列的index都是从0开始 ...
- 【Java】【泛型】
泛型的优点使⽤泛型有下⾯⼏个优点:1.类型安全2.向后兼容3.层次清晰4.性能较⾼,⽤GJ(泛型JAVA)编写的代码可以为java编译器和虚拟机带来更多的类型信息,这些信息对java程序做进⼀步优化提 ...
- 使用JS语句,利用for循环的方法创建表格的两种方法
首先去layui官网下载教程示例,在项目中加载layui.css,layui.js,JQuery.js 第一种: 将jsp语句写成字符串的形式,使用document.write()方式输出: 代码如下 ...
- http_load 高并发测试
安装http_load 下载 sudo wget http://www.acme.com/software/http_load/http_load-09Mar2016.tar.gz 解压 sudo t ...
- sort-归并排序
void sort_merge(vector<int> &v,int left,int right) { if(left>=right) return; int mid=(l ...
- Altium Designer PCB的时候 高亮显示引脚连线
按住Ctrl ,左击连线,就可以高亮显示两个连接的引脚.
- Mac批量转换mp3为caf
创建一个sh文件,输入如下代码后运行. 遍历文件夹中的mp3然后使用afconvert命令进行转换. #!/bin/bash for i in *.mp3; do afconvert $i " ...
- Fiddler 手机抓包介绍
直接打开tools -> Options 进行设置 点击OK,在这里代理就设置完成,一定要重启软件配置才生效,下面是手机端的设置. 手机端代理设置以三星S4为例子,1.如下图真机三星S4设置:找 ...
- 雷林鹏分享:C# 可空类型(Nullable)
C# 可空类型(Nullable) C# 可空类型(Nullable) C# 提供了一个特殊的数据类型,nullable 类型(可空类型),可空类型可以表示其基础值类型正常范围内的值,再加上一个 nu ...
- libavcodec是一款LGPL自由软件编解码库,用于视频和音频数据的编解码工作
http://zh.wikipedia.org/zh-cn/Libavcodec http://baike.baidu.com/view/856526.htm libavcodec是一款LGPL自由软 ...