继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

Oracle Shared Pool机制之——Latches, Locks, Pins and Mutexes

慕桂英546537
关注TA
已关注
手记 301
粉丝 31
获赞 200

本文中,我们将讨论共享池(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冲突。

原文出处:https://www.cnblogs.com/lhdz_bj/p/9454872.html

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP