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

  1. 6 17th, 201020:48
    回复 | 引用 | #1
     

    在Oracle中, Mutex是一个类似于Lock的机制, 与Latch还是有较大的差异, Mutex有锁资源管理, 只是更加轻量级, latch类似于OS的spin_lock机制, 基本的操作类似于Compare and swap (或者Test and Set), 只是在内存中由Oracle进行控制(本人估计可能是为了避免进行过多的Kernel mode/user Mode的切换).

     
  2. 6 17th, 201022:18
    回复 | 引用 | #2
     

    latch是oracle自己实现的,mutex则是OS的系统调用,CAS的原子性是OS提供的,Oracle利用了它的特性。

     
  3. 6 19th, 201019:01
    回复 | 引用 | #3
     

    lock是一个排队机制,MUTEX应该还是和latch的机制差不多,只不过他更加轻量级,并且是通过资源本身上的count标志位来确定能否互斥,oracle的TX lock虽然也是用一个bit位来确定资源是否锁定,但是他需要维护排队信息,还是需要额外的resource的

     
  4. jacky
    6 19th, 201023:25
    回复 | 引用 | #4
     

    mutex是更轻量级的latch,而lock是由enqueue实现的,而enqueue这个结构又是靠latch保护起来的:)

     
  5. 6 21st, 201014:25
    回复 | 引用 | #5
     

    确实记错了啊.. 不过Mutex是os的系统调用吗?

     
  6. logchild
    6 21st, 201018:02
    回复 | 引用 | #6
     

    mutex在innodb中也大有所用

     
  7. jacky
    6 22nd, 201017:34
    回复 | 引用 | #7
     

    准确点说,mutex不是系统调用,而是用系统调用实现的,CAS在很多OS上都有现成的系统调用,由OS来保证其原子性。

     
  8. 7 3rd, 201022:42
    回复 | 引用 | #8
     

    Mutex是操作系统为了实现PV操作提供的原子功能,P/V两个操作都必须是原子的,才能保证并发不被打乱,与其相似的还有信号量Semaphore,这些都是操作系统原理上的东西了

 

posted @ 2013-06-05 14:08  taowang2016  阅读(741)  评论(0编辑  收藏  举报