cursor: mutex s争用本质是游标元数据访问的串行化瓶颈,因高version_count导致mutex s持有时间剧增,需遍历大量子游标比对兼容性字段,引发并发会话排队等待。
因为mutex s争用会串行化游标查找过程,而高version_count让每次查找都要遍历大量子游标
cursor: mutex S 本质是共享访问的串行化瓶颈
当多个会话同时执行同一SQL(sql_id相同),都需要读取该游标的元数据(比如执行计划、绑定信息、环境依赖等),就必须先获取该游标关联的Mutex S。Oracle用Mutex替代老式Latch,虽更轻量,但仍是原子操作——同一时刻只允许一个会话持有S锁进行“读检查”。若此时有另一个会话正以X模式修改该游标(如硬解析、失效重建),S请求就会排队等待。
- 不是锁住整个shared pool,而是锁住单个游标结构体(
address+hash_value) - 等待时间直接计入
time_waited_micro,在v$system_event里可查 - 哪怕只是软解析,只要涉及游标匹配(比如检查子游标是否可重用),也需S锁
version_count过高让Mutex S持有时间变长
一个sql_id下若有几百甚至上千个子游标(version_count > 100就该警惕),那么每次新会话尝试软解析时,Oracle必须遍历整个子游标链表,逐个比对v$sql_shared_cursor里的20+兼容性字段(如BIND_EQUIV_FAILURE、LANG_MISMATCH)。这个遍历过程全程持有Mutex S —— 持有时间与子游标数量成正比。
- 你看到
v$sqlarea里version_count = 8025,意味着每次查找平均要检查数千个子游标 - 遍历本身不耗CPU多,但Mutex S被持续占用,其他并发请求只能排队
- 典型诱因:绑定变量类型不一致(
varchar2vsnumber)、NLS设置漂移、ACS触发子游标分裂
11g中特别容易放大这个问题
Oracle 11.2.0.1存在已知缺陷:子游标匹配逻辑在某些场景下过于保守,加上默认cursor_sharing = EXACT,导致本可复用的游标被强行拆分成多个版本。再加上11g对ACS和Cardinality Feedback的激进启用,进一步推高version_count。
- 11.2.0.1是Bug高发版本,例如
Bug 28794230就直接关联BIND_EQUIV_FAILURE引发的Mutex X/S连锁等待 -
v$mutex_sleep里sleeps值飙升,说明Mutex S请求频繁失败并重试 - CPU使用率可能不高,但
parse time elapsed和hard parse count (total)会异常升高
真正卡住的不是SQL执行,而是“找执行计划”这一步——它被Mutex S死死按在队列里,且越积越多。修复关键不在调参数,而在砍掉那些本不该存在的子游标。否则任何临时flush或purge都只是把火苗暂时压下去,风一吹又燃。











