深入理解Oracle中的Mutex(3)

发表于:2013-10-10来源:IT博客大学习作者:Maclean Liu点击数: 标签:oracle
Mutex的类型Mutex Type Mutex的类型其实就是 mutex对应的客户的名字, 在版本10.2中基本只有KKS使用Mutex,所以仅有3种: Cursor Stat (kgx_kks1) Cursor Parent (kgx_kks2) Curs

  Mutex的类型Mutex Type

  Mutex的类型其实就是 mutex对应的客户的名字, 在版本10.2中基本只有KKS使用Mutex,所以仅有3种:

  Cursor Stat (kgx_kks1)

  Cursor Parent (kgx_kks2)

  Cursor Pin (kgx_kks3)

  在版本11g中扩展了对Mutex的使用,在Library Cache的HASH BUCKET中嵌入了mutex以保护hash bucket,所以多了一种mutex type : Library Cache

  哪些代码函数会申请Mutex?

  Oracle中哪些代码函数会申请Mutex? 例如KKSFBC等,其实很像 V$LATCH的location列

  10.2中最常见的下面的几个函数

  kkspsc0 -负责解析游标 - 检测我们正在解析的游标是否有对象的parent cursor heap 0存在

  kksfbc - 负责找到合适的子游标 或者创建一个新的子游标

  kksFindCursorstat

  11g开始有大量函数需要用到Mutex了

  SQL> select location from X$MUTEX_SLEEP_HISTORY;

  LOCATION

  —————————————-

  kkslce [KKSCHLPIN2]

  kksfbc [KKSCHLFSP2]

  kglhdgn2 106

  kglpin1 4

  kglhdgn2 106

  kglllal1 109

  kglpin1 4

  kglpndl1 95

  kglpin1 4

  kglpin1 4

  kksfbc [KKSCHLFSP2]

  kglhdgn1 62

  kglpnal1 90

  kglllal3 111

  kglpnal1 90

  kglpnal1 90

  kglget2 2

  kglllal3 111

  kglget2 2

  kglobld1 75

  kkslce [KKSCHLPIN2]

  kglpndl1 95

  kglpndl1 95

  kglpin1 4

  kkslce [KKSCHLPIN2]

  kglpin1 4

  kglget2 2

  kglllal1 109

  kgllkc1 57

  kglget2 2

  kglpnal1 90

  kglpin1 4

  kglpin1 4

  kglpin1 4

  kgllkdl1 85

  kglllal3 111

  kgllldl2 112

  kglpin1 4

  kglpndl1 95

  kkslce [KKSCHLPIN2]

  kksLockDelete [KKSCHLPIN6]

  kglpndl1 95

  kkslce [KKSCHLPIN2]

  kglpnal1 90

  kglpin1 4

  kglpin1 4

  kgllldl2 112

  kgllkdl1 85

  kglpin1 4

  kglhdgn2 106

  kglhdgn2 106

  kksLockDelete [KKSCHLPIN6]

  kglhdgn1 62

  Mutex的Get和Sleep

  当一个Mutex被申请时, 一般称为一个get request。 若初始的申请未能得到授权, 则该进程会因为此次申请而进入到255次SPIN中(255是在代码中用常量写死的),每次SPIN循环迭代过程中该进程都会去看看Mutex被释放了吗。

  若该Mutex在SPIN之后仍未被释放,则该进程针对申请的mutex进入对应的mutex wait等待事件中。 实际进程的等待事件和等待方式由mutex的类型锁决定,例如 Cursor pin、Cursor Parent。 举例来说,这种等待可能是阻塞等待,也可以是sleep。

  但是请注意在V$MUTEX_SLEEP_*视图上的sleep列意味着等待的次数。相关代码函数在开始进入等待时自加这个sleep字段。

  等待计时从进程进入等待前开始计算等待时间, 当一个进程结束其等待,则等待的时间加入都总和total中。 该进程再次尝试申请之前的Mutex,若该Mutex仍不可用,则它再次进入spin/wait的循环。

  V$MUTEX_SLEEP_HISTORY视图的GETS列仅在成功申请到一个Mutex时才增加。

  短期持有一个mutex: spin 循环255次一般可以有效以S mode获得一个mutex, 前提是该Mutex 已经被以S mode持有。 简单来说若有2个进程同时以S mode去申请一个Mutex,则稍晚的一个申请者需要进入SPIN并等稍早一点的申请者完成它的例如创建针对该mutex的一个reference的操作,但这都是非常迅速的操作。

  长期持有一个Mutex: 如若一个Mutex已经被某进程以X mode持有, 则往往有其进程以SHRD模式去申请该mutex时仍发现该mutex 以X mode被其他进程所持有,则往往这个EXCL 持有是 LONG_EXCL(可以通过SSD DUMP发现),则后续的申请者往往要进入spin循环,甚至需要等待

  上面我讲了willing-to-wait的mutex, 实际上mutex 的申请也可以是 nowait的。进程以nowait申请mutex时不会进入spin-cycle也不sleep,它只继续常规处理。 当一个nowait get失败时,将增加一次miss,但是实际上V$MUTEX_SLEEP_*中记录的miss不是这样的miss, 视图中记录的miss是等待的次数, 对于真正的miss没有统计项。

  Wait Time等待时间

  类似于latch,spin time 不算做mutex的消耗时间,它只包含等待消耗的时间。

  真正理解Mutex相关的等待

  Mutex数据结构中存放了Holder id持有者ID , Ref Count,和其他Mutex相关的统计信息。 Holder id对应于持有该Mutex的session id (v$session.sid) 。 特别注意, Ref Count是进程并发以S mode参考该Mutex的进程数量(如下文的演示)。

  当一个Mutex被以X mode 持有,则Holder id 为对应持有该mutex的session id,而Ref Count为0。

  每一个共享S mode持有者仅仅增加mutex上的Ref Count。 可供大量session并发以S mode持有参考一个Mutex。 但是注意更新ref count的操作是串行的, 这是为了避免错漏并维护mutex中正确的ref count。

  下面我们详细介绍一个执行游标过程中对mutex share pin的过程:

  某进程以SHRD 模式申请一个Mutex,并尝试临时修改该Mutex的Holder ID

  若该Mutex正被他人更新,则该session会将Holder id设置为本session的sid,之后该进程将增加ref count,之后再清楚mutex上的Holder id。简单来说 这个Holder id是真正做了并行控制的功能。 若该Holder id 被设置了,则说明该Mutex要么被以EXCL模式持有,要么正有一个其他进程在以S mode申请该Mutex的过程中(例如更新Ref Count)。 当更新Ref Count时临时设置holder id的目的就是为了实现避免其他进程并发更新该Mutex的机制。 通过这些例子说明了 , Mutex既可以用作Latch并发控制, 也可用作pin。

原文转自:http://blogread.cn/it/article/6410