發現系統自動統計信息收集任務錯誤運行在業務高峰期(上午10點),經排查為遺留的DBMS_JOB調度策略不當。借此機會全面梳理DBMS_SCHEDULER架構,實現從簡陋Job調度向企業級工作流引擎的升級。
DBMS_SCHEDULER採用「調度計劃、程序邏輯、作業實例」三層解耦,支持複用、版本控制、依賴編排:
| 對象類型 | 核心作用 | 創建包 | 關鍵屬性 |
|---|---|---|---|
| Schedule (調度計劃) | 時間策略模板:頻率、時區、窗口 | CREATE_SCHEDULE | REPEAT_INTERVAL, START_DATE, END_DATE |
| Program (程序邏輯) | 業務邏輯載體:PL/SQL、存儲過程、外部可執行文件 | CREATE_PROGRAM | PROGRAM_ACTION, PROGRAM_TYPE, NUMBER_OF_ARGUMENTS |
| Job (作業實例) | 運行實體:綁定Schedule+Program+參數+資源約束 | CREATE_JOB | JOB_ACTION, SCHEDULE_NAME, PROGRAM_NAME, JOB_CLASS |
BEGIN
DBMS_SCHEDULER.CREATE_SCHEDULE (
schedule_name => 'DAILY_0400_SCHEDULE',
start_date => SYSTIMESTAMP AT TIME ZONE 'PRC', -- 關鍵:指定時區避免夏令時坑
repeat_interval => 'FREQ=DAILY; BYHOUR=4; BYMINUTE=0; BYSECOND=0',
comments => '每日北京時間04:00觸發,適配統計信息收集窗口'
);
END;
/
BEGIN
DBMS_SCHEDULER.CREATE_PROGRAM (
program_name => 'GATHER_STATS_PROG',
program_type => 'PLSQL_BLOCK',
program_action => q'[
BEGIN
DBMS_STATS.GATHER_DATABASE_STATS(
options => 'GATHER AUTO',
degree => DBMS_STATS.AUTO_DEGREE,
cascade => TRUE,
no_invalidate => FALSE
);
END;
]',
number_of_arguments => 0,
enabled => TRUE,
comments => '全庫統計信息自動收集,自適應並行度'
);
END;
/
BEGIN
DBMS_SCHEDULER.CREATE_JOB (
job_name => 'AUTO_STATS_GATHER_JOB',
program_name => 'GATHER_STATS_PROG',
schedule_name => 'DAILY_0400_SCHEDULE',
job_class => 'DEFAULT_JOB_CLASS', -- 可自定義資源消費組
enabled => TRUE,
auto_drop => FALSE, -- 保留歷史日誌
comments => '替代舊DBMS_JOB統計收集任務,修正執行時間窗口'
);
END;
/
-- 基於文件到達/隊列消息觸發
BEGIN
DBMS_SCHEDULER.CREATE_JOB (
job_name => 'ETL_TRIGGER_JOB',
program_name => 'ETL_PROG',
queue_spec => 'ETL_QUEUE_AGENT', -- AQ隊列
event_condition => 'tab.user_data.event_type = ''FILE_ARRIVED''',
parallel_instances => TRUE
);
END;/
BEGIN
DBMS_SCHEDULER.CREATE_CHAIN ('DAILY_ETL_CHAIN');
-- 定義步驟
DBMS_SCHEDULER.DEFINE_CHAIN_STEP ('DAILY_ETL_CHAIN', 'STEP_EXTRACT', 'EXTRACT_PROG');
DBMS_SCHEDULER.DEFINE_CHAIN_STEP ('DAILY_ETL_CHAIN', 'STEP_TRANSFORM', 'TRANSFORM_PROG');
DBMS_SCHEDULER.DEFINE_CHAIN_STEP ('DAILY_ETL_CHAIN', 'STEP_LOAD', 'LOAD_PROG');
-- 定義依賴規則
DBMS_SCHEDULER.DEFINE_CHAIN_RULE ('DAILY_ETL_CHAIN', 'TRUE', 'START STEP_EXTRACT');
DBMS_SCHEDULER.DEFINE_CHAIN_RULE ('DAILY_ETL_CHAIN', 'STEP_EXTRACT SUCCEEDED', 'START STEP_TRANSFORM');
DBMS_SCHEDULER.DEFINE_CHAIN_RULE ('DAILY_ETL_CHAIN', 'STEP_TRANSFORM SUCCEEDED', 'START STEP_LOAD');
DBMS_SCHEDULER.DEFINE_CHAIN_RULE ('DAILY_ETL_CHAIN', 'STEP_LOAD COMPLETED', 'END');
DBMS_SCHEDULER.ENABLE ('DAILY_ETL_CHAIN');
END;/
-- 創建作業類別綁定消費者組
BEGIN
DBMS_SCHEDULER.CREATE_JOB_CLASS (
job_class_name => 'ETL_HIGH_PRIORITY_CLASS',
resource_consumer_group => 'ETL_GROUP', -- 保證ETL獲得CPU份額
logging_level => DBMS_SCHEDULER.LOGGING_RUNS
);
END;/
| DBMS_JOB | DBMS_SCHEDULER | 遷移要點 |
|---|---|---|
| JOB參數:WHAT, NEXT_DATE, INTERVAL | Job + Schedule + Program分離 | 將INTERVAL轉為CALENDAR語法(FREQ=DAILY;BYHOUR=2) |
| 無依賴管理 | Chains支持複雜DAG依賴 | 拆分單體Job為Chain步驟 |
| 日誌查詢困難 | DBA_SCHEDULER_JOB_RUN_DETAILS全維度審計 | 建立標準化監控視圖 |
| 無時區感知 | 原生支持TIME ZONE | 強制指定START_DATE AT TIME ZONE 'PRC' |
-- 任務運行歷史與性能
SELECT job_name, status, error#, actual_start_date, run_duration, cpu_used
FROM DBA_SCHEDULER_JOB_RUN_DETAILS
WHERE job_name = 'AUTO_STATS_GATHER_JOB'
ORDER BY log_date DESC;
-- 即將運行的任務
SELECT job_name, next_run_date, state
FROM DBA_SCHEDULER_JOBS
WHERE enabled = 'TRUE';
DBMS_SCHEDULER不僅是DBMS_JOB的替代品,更是構建企業級數據運維自動化平台的基石。掌握「Schedule/Program/Job」三層解耦、「Chains」依賴編排、「Resource Manager」資源治理三大核心能力,即可從被動的任務調度者進化為主動的數據流程架構師。