19c中cursor: pin S wait on X根因是游标无法共享引发mutex争抢,可通过查询blocking_session定位持锁会话,检查version_count>5、bind_mismatch='Y'及统计信息收集时机来确诊,优先升级至19.20+修复mutex释放延迟Bug。
直接结论:这不是sql写得烂的问题,而是游标无法共享导致多个会话争抢同一个游标的 mutex x 锁;19c 中绝大多数 cursor: pin s wait on x 都能通过绑定变量规范、避免隐式类型转换、控制统计信息刷新节奏来根治,而非调大 shared_pool_size 或重启实例。
怎么快速定位正在持锁的会话和 SQL
19c 已完全支持 BLOCKING_SESSION 字段,无需手动解析 P2RAW:
- 查当前等待者:
SELECT sid, sql_id, blocking_session FROM v$session WHERE event = 'cursor: pin S wait on X'; - 查持锁会话正在干啥:
SELECT sql_id, sql_text, program FROM v$session s JOIN v$sqlarea a ON s.sql_id = a.sql_id WHERE s.sid = &blocking_sid; - 重点看该
sql_id的version_count:SELECT version_count, loaded_versions, users_executing FROM v$sqlarea WHERE sql_id = '&sql_id';—— 若version_count > 5,基本可断定是游标分裂引发的连锁等待
为什么绑定变量不声明类型会导致 cursor: pin S wait on X
Oracle 在软解析时,若绑定变量未显式指定长度或类型(如 PL/SQL 中用 v_id := 100; 后直接拼进 EXECUTE IMMEDIATE),不同调用可能推断出 VARCHAR2(1)、VARCHAR2(32) 等不同类型,触发 BIND_MISMATCH = Y,强制生成新子游标。后续所有对该 SQL 的执行请求,都需排队等第一个会话完成硬解析(持 X 锁)。
- 错误写法示例:
EXECUTE IMMEDIATE 'SELECT * FROM orders WHERE order_id = :1' USING v_order_id;(v_order_id 是 VARCHAR2 类型但值为纯数字) - 正确做法:显式转类型或使用
TO_NUMBER(),或在 PL/SQL 中声明为NUMBER变量 - 验证方式:
SELECT child_number, bind_mismatch FROM v$sql_shared_cursor WHERE sql_id = '&sql_id';—— 凡bind_mismatch = 'Y'的子游标,就是软解析失败的铁证
统计信息自动收集引发的连锁 cursor: pin S wait on X
19c 默认启用 DBMS_STATS.AUTO_TASKS_STATUS,若夜间收集任务恰与业务高峰重叠,且涉及大量表(尤其分区表),会导致成百上千游标同时失效 → 第一个会话重解析持 X 锁 → 其他会话全卡在 cursor: pin S wait on X 上。
- 检查是否踩坑:
SELECT client_name, status, window_group FROM dba_autotask_client WHERE client_name = 'auto optimizer stats collection'; - 临时规避:收集前加
NO_INVALIDATE => FALSE(注意:19c 默认已是FALSE,但老脚本可能仍写TRUE) - 生产建议:对核心大表禁用自动收集,改用带
STALE_PERCENT => 5和GRANULARITY => 'PARTITION'的定制任务,避开高峰时段
容易被忽略的 19c 特有陷阱:_kks_use_mutex_pin 隐含参数与 Bug 修复状态
19c 中 _kks_use_mutex_pin 默认为 TRUE,即强制使用 mutex 替代老式 library cache pin。但部分补丁集(如 19.14 之前)存在 mutex 释放延迟的 Bug(如 Bug 33586785),表现为 cursor: pin S wait on X 持续数十秒不退,且 v$mutex_sleep 中 Cursor Pin 类型的 SLEEPS 异常高。
- 确认当前行为:
SELECT ksppinm, ksppstvl FROM x$ksppi JOIN x$ksppsv USING (indx) WHERE ksppinm = '_kks_use_mutex_pin'; - 不要盲目设为
FALSE:这会退回到更重的 latch 机制,可能引发library cache lock更严重争用 - 优先升级到 19.20+ 或应用最新 RU(Release Update),该类 mutex 持有异常在 19.19 RU 中已明确修复


















