前言
本文主要介绍高级OWI基础的Mutex (互斥锁)相关内容
关于Mutex的概念,我们还是通过下面官方在线文档的描述有一个总体的印象:
Database Concepts 12.2 http://t.cn/R9NOV0I Mutexes A mutual exclusion object (mutex) is a low-level mechanism that prevents an object in memory from aging out or from being corrupted when accessed by concurrent processes. A mutex is similar to a latch, but whereas a latch typically protects a group of objects, a mutex protects a single object. Mutexes provide several benefits: A mutex can reduce the possibility of contention. Because a latch protects multiple objects, it can become a bottleneck when processes attempt to access any of these objects concurrently. By serializing access to an individual object rather than a group, a mutex increases availability. A mutex consumes less memory than a latch. When in shared mode, a mutex permits concurrent reference by multiple sessions.
通过上面的描述,我们知道Mutex和Latch一样都是低级别的保护内存对象的锁机制,并且具有以下的特点:
・一个Mutex仅保护一个对象,会减缓竞争 ・Mutex比Latch使用更少的内存 ・Mutex可以是共享模式的
另外,Mutex还具有以下特点:
・Mutex本身和保护对象是一体的,不像Latch一样有单独的latch池,而且Mutex本身占用内存也更小。 ・Mutex没有等待和持有队列,所以没有排队机制。 ・Mutex具有共享和排他两种模式
Mutex的演化
Mutex (KGX) 是Oracle 推出的用于替代部分Latch和Pin的功能内存锁机制,以下是部分演化历史:
・10.2.0.1版本开始实现Mutex功能(默认不使用,通过隐含参数_kks_use_mutex_pin控制)。
・10.2.0.2以后版本默认使用Mutex,但仅仅对共享游标的部分操作(KKS)使用Mutex保护。
・11.1 应用范围进一步扩大,对library cache(KGL)的同一Hash Bucket访问时也使用Mutex保护,出现了library cache mutex等。
・11.1.0.7以后的版本,Oracle针对于library cache(KGL)相关的Mutex, 追加了一个_kgl_mutex_wait_time隐含参数,用于控制获得Mutex过程中的获取动作;
当_kgl_mutex_wait_time不为0(默认值)时,如果获取超过spin的回数,仍未获取到Mutex的话,进程不再和以前版本一样进行退让(yielding)而进行睡眠(waiting),并且睡眠时间为_kgl_mutex_wait_time参数指定的值。
例:(11.2.0.2)
SQL> select a.ksppinm "Parameter",a.KSPPDESC "Description",b.ksppstvl "Value" from x$ksppi a, x$ksppcv b where a.indx = b.indx and a.ksppinm like '%_mutex%'; Parameter Description Value -------------------- ---------------------------------------- ---------- _kgl_mutex_wait_time KGL mutex wait time 0
・基于11g Enhancement Bug 10411618 (在PSU 11.1.0.7.9和PSU 11.2.0.2.2以后的版本进行了修改)等,Mutex机能进行了一系列的机能强化;
主要引入了包括以下参数,可以对Mutex的获得过程根据应用需要进行调整。
_mutex_spin_count: 用于控制在获得Mutex过程过程中spin的回数(默认255); 超过指定的spin的回数,进程会进行退让或者等待(yielding/waiting)。 (※Bug 10411618修正之前版本为固定值255) _mutex_wait_scheme: 用于控制Mutex的获得机制。(默认2) ・_mutex_wait_scheme = 0 (Yield) Bug 10411618加强的机能会被禁止; 和之前11.2.0.1版本的动作相同,超过指定的spin的回数仍然没有获得Mutex,进程不会发生睡眠(Sleep)而是进行退让(Yield)CPU,然后再spin。 ・_mutex_wait_scheme = 1 & _mutex_wait_time = T (SLEEP ) 如果获取超过spin的回数,仍未获取到Mutex的话,进程会进行睡眠(Sleep)然后再spin,并且每次睡眠时间为T毫秒(milli-seconds). ・_mutex_wait_scheme = 2 & _mutex_wait_time = T (EXP BACKOFF SLEEP ) 如果获取超过spin的回数,仍未获取到Mutex的话,会进行睡眠(Sleep)然后再spin,并且每次睡眠时间由称为指数退让算法(exponential backoff Sleep)决定,其最大的睡眠时间为T厘秒(centi-seconds)。 _mutex_wait_time: 用于和_mutex_wait_scheme并用,指定时间(默认1)。
注:
・关于指数退让算法(exponential backoff Sleep)可参考【高级OWI之Latch(闩锁)】一文中的介绍。
・在Bug 10411618 修正的版本中,_kgl_mutex_wait_time参数被_mutex_wait_time所替代。
例:(on Ver 11.2.0.2.2~12.2)
SQL> select a.ksppinm "Parameter",a.KSPPDESC "Description", b.ksppstvl "Value" from x$ksppi a, x$ksppcv b where a.indx = b.indx and a.ksppinm like '%_mutex%'; Parameter Description Value -------------------- --------------------- ---------- _mutex_wait_time Mutex wait time 1 _mutex_spin_count Mutex spin count 255 _mutex_wait_scheme Mutex wait scheme 2
・关于yielding和waiting:
yielding: 相当于Linux中sched_yield()这个函数的动作; 当前进程对CPU进行退让,可以让另一个级别等于或高于当前进程的进程先运行。 如果没有符合条件的进程,那么这个函数将会立刻返回,然后继续执行当前进程的程序。 waiting: 当前运行的进程睡眠一段时间,进入不可运行状态,这段时间会释放CPU。
新版本中Mutex获取过程中yielding/waiting/Pining逻辑的简要流程图,可以简要归纳如下:
参考:
andrey nikolaev’s blog
http://t.cn/RCRdmMb
Mutex waits. Part III. Contemporary Oracle wait schemes diversity.
Mutex的结构和获取
Mutex的实现一般需要使用操作系统平台的compare-and-swap (CAS) 操作,对于不支持CAS的操作系统平台如HP-UX PA-RISC,Oracle数据库会使用一段称为Mutex latches的代码模拟CAS操作。
但在12.2版本以后,由于Oracle数据库不再和HP-UX PA-RISC兼容,所以仅支持CAS操作的实现方式。
Mutex的结构中一般会包含以下信息:
Holder Id:以排他模式(X Mode)持有Mutex的会话ID。 Ref count:以共享模式(S Mode)持有Mutex的会话数。 mutex-related statistics:其他Mutex相关的统计信息。
当Mutex的Holder Id不为空时,表示该Mutex以排他模式(X Mode)被持有, 以排他模式(X Mode)被持有Mutex一般包括以下情况:
・某进程正以排他模式(X Mode)持有该Mutex; 此时Holder Id是持有Mutex的会话ID,Ref count为0。 ・以共享模式(S Mode)持有Mutex的进程数发生变化(增加或者减少); 因为更新Ref count的操作需要串行,所以需要排他模式(X Mode)持有。 此时Holder Id是正在更新Ref count的会话ID,Ref count可能不为0。 (这通常仅仅是个中间状态,会在极短的时间内完成,Ref count更新后,Holder Id重置为空)
如上所述,通过对Mutex的结构中Holder Id和Ref count的更新,可以实现对Mutex的模式控制,以下是以cursor: pin为例介绍mutex的获取和释放过程。
※注1:
・其他某进程正以排他模式(X Mode)持有该Mutex时,等待事件为cursor: pin S wait on X ・其他某进程由于更新Ref count的操作而以排他模式(X Mode)持有该Mutex时,等待事件为cursor: pin S
参考:
compare-and-swap (CAS)
https://en.wikipedia.org/wiki/Compare-and-swap
Mutex的类型和等待事件
根据Mutex保护的功能不同,可以把Mutex分成不同的类型;
为了方便诊断,Oracle针对不同类型的Mutex定义了不同的等待事件。
最常见的Mutex是Cursor相关(KKS)和library cache(KGL)相关的Mutex,相对应的最常见的等待事件包括如下:
cursor: mutex X cursor: mutex S cursor: pin X cursor: pin S cursor: pin S wait on X library cache: mutex X library cache: mutex S
对于各种Mutex的类型和等待事件,可参照MOS文档:
Troubleshooting: Waits for Mutex Type Events (Doc ID 1377998.1) FAQ: 'cursor: mutex ..' / 'cursor: pin ..' / 'library cache: mutex ..' Type Wait Events (Doc ID 1356828.1) Troubleshooting 'library cache: mutex X' Waits. (Doc ID 1357946.1)
其他内容将在以后的文章中进行介绍。
用碎片化的时间,一点一滴地学习一套系统化的知识。