Mutex(测)(一)

2015-07-24 07:25:28 · 作者: · 浏览: 2

游标共享如何使用Mutex

kks 使用mutex以便保护对于下述基于parent cursor父游标和子游标child cursor的一系列操作

对于父游标parent cursor的操作:

基于发生的不同操作,对应不同的等待事件:
在某个父游标名下创建一个新的游标 ==> cursor:mutex X
检查一个父游标 ==> cursor:mutex S
绑定值捕获 ==> cursor:mutex X
保护父游标的mutex嵌入在父游标结构内
针对父游标parent cursor的Mutex类型为’Cursor Parent’ (kgx_kks2).
针对父游标parent cursor的Mutex等待事件均为’ Cursor: mutex *’的形式

Mutex是如何替代library cache pin来保护cursor heap的?

传统的’library cache pin’在10.2.0.2之后默认被取代, 此处PIN被Mutex及其ref count取代。 当进程执行游标语句时或者需要PIN,或者需要hard parse一个子游标heap。
在版本10.2.0.1中, 使用mutex部分代码替代PIN的功能默认是不激活的,实际上这取决于隐藏参数_KKS_USE_MUTEX_PIN,在10.2.0.2之后_KKS_USE_MUTEX_PIN默认为TRUE。 换而言之在版本10.2中我们还是可以关闭KKS使用MUTEX替代PIN保护CURSOR的, 但是在版本11g中则几乎无法关闭MUTEX。 注意10.2中仅当KKS真正使用MUTEX时,library cache pin不再用作cursor pin。
基于对不同的游标统计信息的操作有不同的等待事件:
为执行某个SQL而PIN一个游标Cursor ==>Cursor: Pin S Wait on X
当执行一个游标而PIN Cursor,而该Cursor正被其他进程以S mode检测 ==> cursor:pin S
当试图重建一个游标Cursor ==> Cursor: pin X 该等待事件一般不太会看到,因为当一个游标正被执行,且其需要重建时会有另一个游标被创建
保护游标的mutex嵌入在游标结构内
Mutex类型为’Cursor Pin’ (kgx_kks3)
等待事件均为 ‘cursor: pin *’的形式

KKS使用MUTEX情况下SQL语句的 解析与执行的收益

在版本10.2中, 以下是几个SQL解析与执行从MUTEX哪里获得主要收益:

在某个父游标下构建一个新的子游标
首先这种构建新子游标的操作更廉价了, 当时Maclean仍要告诫你 一个父游标下过多的子游标仍不是一件好事情
对父游标的检测
在找到一个合适的游标并执行前,父游标需要被适当检测。 对父游标的这种检测目前也使用mutex来保护了,所以这种检测更的成本更低了
对于已经加载在Library Cache 中的SQL语句重复执行
常规情况下,当一个进程要执行SQL游标前总是必须要先pin它
不使用MUTEX的情况:若游标处于OPEN状态下以便今后的重复执行,且参数cursor_space_for_time(CSFT 目前已不推荐使用该参数)为TRUE,则每一次重复执行可以不需要library cache pin。 若游标处于OPEN状态下但是cursor_space_for_time=false,则进程在重复执行SQL游标前总是要先拿library cache pin
使用MUTEX的情况: 相反,若使用mutex来替代library cache pin时,则无需关心cursor_space_for_time 。 仅第一个进程需要做一个PIN他后续进程都只需要简单地在对应保护cursor heap的mutex上拿一个共享reference 。

真正理解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。
若Holder id已被设置,则申请进程将可能进入等待事件 。 例如若当前Mutex的持有者进程正以X mode更新该Mutex,则申请者的等待事件应为”cursor: pin S on X” 。 而若当持有者Holder并不是”真的要持有” 该Mutex,而仅仅是尝试更新其Ref Count,则第二个进程将等在’ Cursor :pin S’等待事件上; 实际正在更新Ref count的操作时很快的,是一种轻微的操作。 当第一个进程正在更新mutex,则后续的申请进程将进入spin 循环中255次等待前者结束。 当mutex上不再有 Holder id时(如前者的进程已经更新完Ref Count)时, 则申请者进程将Holder ID设为自身的SID,并更新Ref Count,并清除Holder id。 若在255次循环SPIN后mutex仍不被释放,则该进程进入等待并不再跑在CPU上。

Mutex的相关统计视图

V$MUTEX_SLEEP

shows the wait time, and the number of sleeps for each combination of mutex type and location.

Column Datatype Description
MUTEX_TYPE VARCHAR2(32) Type of action/object the mutex protects
LOCATION VARCHAR2(40) The code location where the waiter slept for the mutex
SLEEPS NUMBER Number of sleeps for this MUTEX_TYPE and LOCATION
WAIT_TIME NUMBER Wait time in microseconds

V$MUTEX_SLEEP