Oracle Mutex实现机制
我们都知道Latch是Oracle用来在内存中做串行控制的机构,从10g R2开始,Oracle引入了一个新的技术-Mutex。Mutex并不是Oracle的发明,而是系统提供的一个底层调用,Oracle只是利用它实现串行控制的功能,并替换部分Latch。
Mutex中有两个变量:分别是Holider identifer和Reference count,Holider identifer记录持有mutex的SID,而Reference count是一个计数,记录了当前正在以share方式访问mutex的数量,每当session以share方式持有mutex时,计数会加1,而释放时会减1。如果Reference count大于零,则表示该内存结构正在被Oracle pin住。
我们看一段伪代码,演示mutex的申请过程:
Function Mutex_get(mutex_name) { if mutex.holder:=SID case mode: 'exclusive': if mutex.ref_count=0 return TRUE else mutex.holder.clear; reture FALSE end if 'share': mutex.ref_count++ mutex.holder.clear return TRUE end case else reture FALSE end if }
Mutex是如何实现串行控制的,实际上它是利用了操作系统的一个原子操作CAS(compare-and-swap)实现的。我们看到函数的开始处:mutex.holder:=SID,将SID赋值给mutex的Holider Identifer,这里就是一个原子的CAS操作,首先比较mutex.holder是否为空,如果不为空则赋值session的SID。CAS操作由OS来保证其原子性,在同一时刻这个操所是串行的。如果这个赋值操作失败,整个申请过程失败。赋值成功后,如果是share方式,则mutex.ref_count加1,并清空mutex.holder,如果是exclusive方式,需要判断mutex.ref_count是否为零(是否被pin住),如果大于0,则失败,并清空mutex.holder,如果等于0,则成功,这时不清空mutex.holder,保持当前session对mutex的exclusive占用,直到释放为止。
Mutex相比latch带来了以下的好处:
1.更少的资源消耗,mutex与latch不同,它不是独立存在的,而是在每个内存结构中,并随着内存结构创建和释放,mutex同时也被创建和释放。mutex暂用的空间比latch小很多,创建和释放消耗更少的资源。
2.有效降低竞争,因为mutex是每个内存结构中的一部分,这样意味着mutex的数量可以有很多,而不同于latch,一个latch需要管理很多个内存结构,当你访问同一latch管理的不同内存结构时,也会发生竞争,而mutex则不会。另外,因为latch的数量有限,很多时候latch本身的竞争会很厉害,之前,我们只能增加latch数量或者减少latch持有的时间,而现在,mutex是一个更好的选择。
3.更快的pin,当block被访问时,它必须被pin在buffer cache中,当一个cursor执行时,它也必须被pin在library cache中,如果大量并发频繁执行同一个cursor,library cache pin会耗费大量的CPU资源。而mutex使用reference count来解决并发访问的问题,只要它大于零,就表示它已经被pin在了内存中,不能被交换出去。而且mutex.ref_count++这个操所是非常快的,只占用非常少的资源。
Mutex申请的过程和latch类似,同样需要spin和sleep,不同的是Oracle硬编码了mutex spin的次数为255次(Latch spin的次数默认为2000,由隐含参数_spin_count控制)。latch sleep会随着等待次数的逐步增加,每次sleep的时间也会逐步增加。而mutex sleep则比较特别,它有三个选项,分别是yield CPU,sleep或者block other process,允许开发人员来决定采用哪种选项。
由于在某些RISC的操作系统中(HP-UNIX),由于系统不支持CAS操作,Oracle通过创建一个latch pool来模拟了CAS操作,被称为KGX latch,如果你发现系统中存在这种latch竞争,说明操作系统不支持CAS操作,可以通过_kks_use_mutex_pin关闭mutex。
mutex主要使用在library cache中,用来取代原来的library cache pin和library cache lock,关于library cache中锁的实现机制,我会在另外一篇文章中说明。
–EOF–
注:有关CAS,可以参考wiki上的说明。
引自:http://www.hellodb.net/2010/06/oracle-mutex.html
在Oracle中, Mutex是一个类似于Lock的机制, 与Latch还是有较大的差异, Mutex有锁资源管理, 只是更加轻量级, latch类似于OS的spin_lock机制, 基本的操作类似于Compare and swap (或者Test and Set), 只是在内存中由Oracle进行控制(本人估计可能是为了避免进行过多的Kernel mode/user Mode的切换).
latch是oracle自己实现的,mutex则是OS的系统调用,CAS的原子性是OS提供的,Oracle利用了它的特性。
lock是一个排队机制,MUTEX应该还是和latch的机制差不多,只不过他更加轻量级,并且是通过资源本身上的count标志位来确定能否互斥,oracle的TX lock虽然也是用一个bit位来确定资源是否锁定,但是他需要维护排队信息,还是需要额外的resource的
mutex是更轻量级的latch,而lock是由enqueue实现的,而enqueue这个结构又是靠latch保护起来的:)
确实记错了啊.. 不过Mutex是os的系统调用吗?
mutex在innodb中也大有所用
准确点说,mutex不是系统调用,而是用系统调用实现的,CAS在很多OS上都有现成的系统调用,由OS来保证其原子性。
Mutex是操作系统为了实现PV操作提供的原子功能,P/V两个操作都必须是原子的,才能保证并发不被打乱,与其相似的还有信号量Semaphore,这些都是操作系统原理上的东西了