定时任务引发的负载峰值源于DBMS_SCHEDULER或DBMS_JOB作业在固定时间集中触发并争用资源;需通过dba_scheduler_job_run_details等视图交叉比对AWR快照与作业执行窗口,结合ASH分析会话堆栈定位瓶颈,并检查资源组、SQL效率、锁竞争及PL/SQL休眠等问题。

定时任务引发的负载峰值,通常不是“突然出现”,而是 DBMS_SCHEDULER 或 DBMS_JOB 作业在固定时间点集中触发、资源争用放大后的结果。直接看 top 或 AWR report 只能看到“CPU高”“IO陡增”,但抓不到源头——必须把作业调度时间、执行逻辑、资源占用三者对齐。
怎么确认是定时任务导致的峰值?
别先翻代码,先查数据库里“谁在那个时间点醒了”。关键动作是交叉比对 AWR 快照时间与作业实际运行窗口:
- 用
dba_scheduler_job_run_details查指定时间段内所有作业执行记录:SELECT job_name, actual_start_date, status, error#, cpu_used FROM dba_scheduler_job_run_details WHERE actual_start_date >= TO_DATE('2026-07-26 02:00:00', 'YYYY-MM-DD HH24:MI:SS') AND actual_start_date <= TO_DATE('2026-07-26 02:15:00', 'YYYY-MM-DD HH24:MI:SS') ORDER BY actual_start_date; - 同步查该时段 AWR 报告中 Top SQL 的
SQL_ID,再用dba_hist_sqltext反查语句,看是否匹配作业中调用的存储过程或匿名块 - 注意:
DBMS_JOB的作业日志不在dba_scheduler_job_run_details,得查dba_jobs+dba_jobs_running,且其next_date字段受INTERVAL表达式影响,容易误判执行时刻
为什么作业一跑就卡住整个实例?
常见原因不是 SQL 慢,而是作业设计没隔离资源边界:
- 作业未设置
resource_consumer_group,默认走DEFAULT_CONSUMER_GROUP,和前台应用抢同一组 CPU/IO 资源池 - 批量更新/删除未加
WHERE条件或未分批,触发全表扫描+大量回滚段写入,拖慢LGWR和DBWn - 调用
UTL_FILE写文件时路径权限不对,作业卡在 OS 层等待超时(错误常被吞掉,只留ORA-29280或无声失败) - 多个作业依赖同一张状态表做
SELECT FOR UPDATE NOWAIT,但未处理ORA-00054异常,导致重试风暴
如何快速定位作业内部瓶颈?
别靠猜,用 ASH 数据“倒放录像”:
- 从
v$active_session_history中提取峰值时段的会话堆栈:SELECT sql_id, event, p1text, p1, session_state, blocking_session FROM v$active_session_history WHERE sample_time >= TIMESTAMP'2026-07-26 02:05:00' AND sample_time <= TIMESTAMP'2026-07-26 02:07:00' AND session_type = 'BACKGROUND' AND program LIKE '%J0%';—— 注意J0是 scheduler job slave 进程标识 - 若看到大量
enq: TX - row lock contention,说明作业在串行化更新;若全是db file sequential read且p1指向同一数据文件号,大概率是索引失效或统计信息陈旧 - 特别留意
PL/SQL lock timer事件——这代表作业里写了DBMS_LOCK.SLEEP,但没控制好循环次数,成了“伪定时器”
临时缓解但不治本的操作清单
上线前压测没做够,现在只能边跑边控:
- 暂停非核心作业:
EXEC DBMS_SCHEDULER.DISABLE('DAILY_CLEANUP_JOB');,别用STOP_JOB,它可能残留事务 - 手动调整作业优先级:
DBMS_SCHEDULER.SET_ATTRIBUTE('HOURLY_REPORT_JOB', 'job_priority', 1);(数值越小优先级越高,系统默认为 3) - 强制刷新统计信息:
DBMS_STATS.GATHER_TABLE_STATS(ownname => 'APP_OWNER', tabname => 'FACT_SALES', method_opt => 'FOR ALL COLUMNS SIZE AUTO');,尤其针对作业频繁访问的分区表 - 检查归档模式是否开启:
ARCHIVE LOG LIST;—— 若作业含大量 DML 且归档未启用,LOG_ARCHIVE_DEST_1空间满会导致作业挂起并阻塞其他会话
最麻烦的不是查出哪个作业有问题,而是这个作业背后绑着上游业务系统的调度策略、下游报表的依赖链、以及 DBA 自己写的清理脚本——改一点,全链路都要重新验证。所以诊断时,一定要把 job_name 和业务含义对上,而不是只盯着技术指标。


















