执行计划不稳定导致反复硬解析,因Oracle 12c优化器对统计信息更敏感,RAC环境下节点间同步延迟或不一致会触发游标失效,造成同一存储过程在不同会话中生成不同执行计划,首次执行慢、后续变快又突然变慢,典型表现为v$sql中parse_calls > executions。
执行计划不稳定导致反复硬解析
oracle 12c优化器对统计信息更敏感,尤其在rac环境下,节点间统计信息同步延迟或不一致时,dbms_stats收集后可能触发游标失效,导致同一存储过程在不同会话中生成不同执行计划。首次执行慢、后续变快又突然变慢,典型表现是v$sql中parse_calls > executions——说明每次调用都在硬解析,而非复用已有游标。
实操建议:
- 检查该存储过程涉及的SQL是否被频繁
INVALIDATE:查v$sql中对应sql_id的invalidations字段是否大于0 - 禁用自动统计信息收集任务临时验证:
EXEC DBMS_AUTO_TASK_ADMIN.DISABLE(client_name => 'auto optimizer stats collection', operation => NULL, window_name => NULL); - 手动锁定关键表统计信息:
EXEC DBMS_STATS.LOCK_TABLE_STATS('SCHEMA_NAME', 'TABLE_NAME');,避免夜间作业误刷
共享池争用加剧,尤其在RAC多节点场景
12c默认启用_kgl_large_heap_assertions等严格校验,硬解析内存分配开销比11g高30%以上;RAC中Library Cache不跨节点共享,但序列、同义词、视图定义等对象若未在所有节点预热,就会造成某节点反复硬解析——你看到“PL/SQL里快、JOB里慢”,很可能是因为JOB调度到未预热的节点上执行。
实操建议:
- 确认共享池是否被压到临界值:
SELECT component, current_size/1024/1024 MB FROM v$memory_dynamic_components WHERE component = 'shared pool';,12c RAC建议不低于1.5GB - 在所有RAC节点上手动预热关键对象:
SELECT * FROM v$database;、SELECT * FROM v$instance;,再执行一次你的存储过程 - 对存储过程中高频访问的包体做显式KEEP:
EXEC DBMS_SHARED_POOL.KEEP('SCHEMA.PACKAGE_NAME', 'P');,注意包名大小写和所有权
序列调用在循环内未批量处理
如果你的存储过程里有类似FOR i IN 1..1000 LOOP SELECT seq.NEXTVAL INTO v_id FROM dual; ... END LOOP;这种写法,在12c中会因序列CACHE默认仅20,每20次就触发一次磁盘重载+enq: sq - contention等待,而11g对此类争用容忍度更高。JOB环境通常并发更低、资源更紧张,放大该问题。
实操建议:
- 立刻检查序列CACHE值:
SELECT cache_size FROM dba_sequences WHERE sequence_name = 'YOUR_SEQ'; - 增大CACHE(如设为1000):
ALTER SEQUENCE your_seq CACHE 1000; - 改用BULK COLLECT批量取值,避免循环内逐条调用:
SELECT your_seq.NEXTVAL BULK COLLECT INTO v_ids FROM DUAL CONNECT BY LEVEL - 若主键逻辑允许,直接迁移到
IDENTITY列:id NUMBER GENERATED ALWAYS AS IDENTITY CACHE 1000,彻底绕过PL/SQL层序列调用
隐式类型转换与绑定变量窥探恶化
12c优化器对绑定变量值更激进地做“窥探”(bind peeking),如果存储过程参数传入NULL或极偏态值,可能生成一个仅对该值最优、但对其他值灾难性的执行计划,并固化进共享池。JOB调用时参数固定,却可能命中这个劣质计划;而PL/SQL测试时用了不同参数,走了另一条路径。
实操建议:
- 查该SQL的
v$sql_plan_statistics_all,对比actual_elapsed_time和optimizer_cost是否严重偏离 - 对关键WHERE条件加
/*+ BIND_AWARE */提示(需12.1.0.2+),让优化器为不同绑定值生成多个子游标 - 避免在存储过程中用
TO_NUMBER()、TO_CHAR()包裹参数做条件判断——这会强制隐式转换,破坏绑定变量复用 - 用
DBMS_SQLTUNE.CREATE_SQL_PLAN_BASELINE固化已验证的高效执行计划,防止被自动淘汰
真正卡住的往往不是版本升级本身,而是12c更严格的资源管控和更敏感的优化器行为暴露了原来就存在的设计毛刺:没锁统计、没预热对象、没调序列、没管绑定变量。这些点单个看都不致命,叠在一起就让JOB执行从秒级拖到分钟级。


















