今天半夜22:25 左右,某套核心系统突然出现大量应用连接超时。登录 OEM 后,发现 ASH 里两条等待事件一路飙红: • cursor: pin S wait on X(峰值 783 个会话) • library cache lock(峰值 311 个会话)
很多 DBA 第一次遇到这种场景时,会本能地把目光聚焦在 “cursor: pin S wait on X”,因为它出现的会话最多、最显眼。但 ASH 的阻塞链(Blocking Session Tree)告诉我们:所有 pin S 会话都只是“受害者”,真正的罪魁祸首是 library cache lock。于是问题被拆成两步:
- library cache lock 最早是什么时候开始的?
- 谁又在阻塞 library cache lock?
一、时间点回溯 通过 DBA_HIST_ACTIVE_SESS_HISTORY 定位第一条 library cache lock 的记录:
TIME EVENT SESSION_ID BLOCKING_SESSION
22:00:33 library cache lock 1723 1349
也就是说,故障根因从 22:00:33 就已埋下。
二、阻塞链逐级展开 SESSION 1723 • 执行的模块:DBMS_STATS(自动统计信息收集作业) • 状态:持续处于 library cache lock,并被 1349 阻塞
SESSION 1349 • 执行的模块:Auto SQL Tuning Task(SYS_AUTO_SQL_TUNING_TASK) • 当前等待:db file parallel read(在做 I/O) • 状态:未被任何其他会话阻塞,处于“链头”位置
至此,链路清晰: Auto SQL Tuning Task(1349) → library cache lock → DBMS_STATS(1723) → cursor: pin S wait on X(大量应用会话)
三、为什么 Auto SQL Tuning 会锁 Library Cache? Auto SQL Tuning 在创建/删除 SQL Profile、Index 或 SQL Patch 时,需要对相关 cursor 加排他型 Library Cache Lock(mode 3)。而 22:00 又是默认的维护窗口,两个自动任务正好撞车:
- Auto SQL Tuning 正在做 I/O(读历史执行信息)并持有 Library Cache Lock;
- 同时 Auto Stats 也要解析同一个 cursor,申请 Library Cache Lock(mode 2/3)。 由于前者持有排他锁,后者只能排队;后者排队的锁又阻塞了大批后续软解析,于是爆发连锁等待。
四、如何避免重演 Auto SQL Tuning 与 Auto Space Advisor 默认在夜间维护窗口并行跑,对 I/O、Library Cache、Latch 都有潜在冲击。对于 OLTP 核心库,常见做法是“关掉再说”:
— 关闭 Auto SQL Tuning BEGIN DBMS_AUTO_TASK_ADMIN.DISABLE( client_name => ‘sql tuning advisor’, operation => NULL, window_name => NULL); END; /
— 关闭 Auto Space Advisor BEGIN DBMS_AUTO_TASK_ADMIN.DISABLE( client_name => ‘auto space advisor’, operation => NULL, window_name => NULL); END; /
关闭后,如果仍有统计信息收集需求,可以:
- 手动收集:DBMS_STATS.GATHER*STATS;
- 或者把自动任务改到业务量更低的时段,并限制并行度(DEGREE)。
五、小结 • “cursor: pin S wait on X” 只是表象,真正的根因往往在更高层级的 Library Cache Lock。 • ASH 的 Blocking Session Tree 是定位连锁等待的最快路径。 • Oracle 的自动任务(Auto SQL Tuning、Auto Space Advisor、Auto Stats)在维护窗口内可能互相阻塞;对高并发 OLTP 系统,建议关闭或错峰。
希望这篇踩坑记录能帮到你。如果你也曾被深夜的 Library Cache Lock 折磨过,欢迎留言交流更多“救火”姿势。