Oracle 定時任務詳解(dbms_scheduler,dbms_job)

1 概述

在這裏插入圖片描述

1.1 基礎數據準備

CREATE TABLE test_job (
   job_name   VARCHAR2(30),
   start_date DATE
);
CREATE OR REPLACE PROCEDURE p_scheduler_test AS
   v_sql_insert VARCHAR2(200);
BEGIN
   -- 記錄 job 信息
   v_sql_insert := 'INSERT INTO test_job(job_name, start_date) VALUES(:b1, :b2)';

   EXECUTE IMMEDIATE v_sql_insert
      USING 'TEST_JOB_NAME_02', SYSDATE;

   COMMIT;
END;
/

2 dbms_scheduler

個人理解: scheduler 和 program 主要是爲了提取 job 中重複的內容,使 job 調用寫法更加簡單。

功能 解釋
scheduler 調度器。定義 scheduler 名稱、起止時間、調用頻率等參數
program 程序。scheduler 具體要乾的事兒
job 整個調度。可以依賴 program 和 scheduler,也可以直接寫入 program 和 scheduler 對應的參數

scheduler:調度器。定義 scheduler 名稱、起止時間、調用頻率等參數

-- 創建
BEGIN
   dbms_scheduler.create_schedule(schedule_name   => 'SYSTEM.TEST_SCHEDULER_NAME_01', -- 記得帶屬主!
                                  start_date      => SYSDATE, -- 開始執行時間,默認當前
                                  repeat_interval => 'FREQ = DAILY; INTERVAL = 1', -- 建議使用: 日曆格式
                                  end_date        => SYSDATE + 7, -- 執行結束時間,默認永久
                                  comments        => '每天執行'); -- 備註信息
END;

-- 查詢
SELECT * FROM dba_scheduler_schedules t WHERE t.owner = 'SYSTEM';

-- 刪除
BEGIN
   dbms_scheduler.drop_schedule(schedule_name => 'SYSTEM.TEST_SCHEDULER_NAME_01', -- 記得帶屬主!
                                force         => TRUE);
END;

program:程序。scheduler 具體要乾的事兒

-- 創建
BEGIN
   dbms_scheduler.create_program(program_name   => 'SYSTEM.TEST_PROGRAM_NAME_01',
                                 program_type   => 'PLSQL_BLOCK', -- 同 job_type
                                 program_action => 'INSERT INTO test_job(job_name, start_date) VALUES(''TEST_JOB_NAME_01'', SYSDATE);',
                                 enabled        => TRUE,
                                 comments       => 'program_name 備註信息');
END;

-- 查詢
SELECT * FROM dba_scheduler_programs t WHERE t.owner = 'SYSTEM';

-- 刪除
BEGIN
   dbms_scheduler.drop_program(program_name => 'SYSTEM.TEST_PROGRAM_NAME_01',
                               force        => TRUE);
END;

job:整個調度

-- 創建,有兩種方式
-- 1.直接創建

-- 2.scheduler + program
BEGIN
   dbms_scheduler.create_job(job_name            => 'SYSTEM.TEST_JOB_NAME_02',
                             program_name        => 'SYSTEM.TEST_PROGRAME_NAME_01',
                             schedule_name       => 'SYSTEM.TEST_SCHEDULE_NAME_O1',
                             enabled             => TRUE,
                             comments            => 'program + schedule 方式創建 job');
END;

-- 查詢
SELECT * FROM dba_scheduler_jobs t WHERE t.owner = 'SYSTEM';
SELECT to_char(t.log_date, 'YYYY-MM-DD HH24:MI:SS'), t.*
  FROM dba_scheduler_job_log t
 WHERE t.owner = 'SYSTEM'
 ORDER BY t.log_date DESC;

-- 刪除
BEGIN
   dbms_scheduler.drop_job(job_name => 'SYSTEM.TEST_JOB_NAME_02', 
                           force    => force);
END;

2.1 創建

擁有 create job 權限的用戶才能創建定時任務:

SELECT * FROM dba_sys_privs t WHERE t.privilege LIKE '%JOB' ORDER BY 1;
  • 缺省屬主的情況下,job 會被創建在當前的 schema 下,並且是沒有激活的;
  • 如果要使 job 已創建就自動激活,需要顯式的設置 enabled 屬性爲 true
  • 創建 job 有以下兩種方式
創建 job 的方式 解釋
dbms_scheduler.create_job 直接創建 job
dbms_scheduler.create_schedule + dbms_scheduler.create_program 引用 scheduler + program

方式1:dbms_scheduler.create_job

  • 可通過 PL/SQL 提示(或按 F6 提示)進行查看,具體的可以鼠標左鍵點進去,查看包頭說明
  • []:可選項 ,其它:必填項
  • 其它過程查看方式相同,就不再贅敘

在這裏插入圖片描述

示例:每分鐘執行一次 job,執行 3 次後,自動刪除 job

若設置了 end_date,到達 結束時間時,任務會被自動刪除
若未設置 end_date,那麼 任務會一直執行

DECLARE

BEGIN
   dbms_scheduler.create_job(job_name        => 'SYSTEM.TEST_JOB_NAME_01',
                             job_type        => 'PLSQL_BLOCK',
                             job_action      => 'INSERT INTO test_job(job_name, start_date) VALUES(''TEST_JOB_NAME_01'', SYSDATE);',
                             start_date      => SYSDATE,
                             repeat_interval => 'freq = minutely; interval = 1',
                             end_date        => SYSDATE + 3 / (24 * 60),
                             enabled         => TRUE,
                             comments        => '每 1 分鐘打印當前時間');
END;
/

參數說明:

1. job_name: job 名稱

2. job_type: job 類型,
	(1) STORED_PROCEDURE: 存儲過程
	(2) PLSQL_BLOCK: PL/SQL(3) EXECUTABLE: 外部程序(可以是一個 shell 腳本,也可以是操作系統級別的指令)	 

3. job_action: job 動作. 根據不同的 job_type, job_action 有不同的含義
	(1) 如果 job_type 指定的是 存儲過程,就需要指定存儲過程名
	(2) 如果 job_type 指定的是 PL/SQL,就需要輸入完整的 PL/SQL 代碼
	(3) 如果 job_type 指定的是 外部程序, 就需要輸入腳本名稱或操作系統的指定名稱

4. repeat_interval: 重複間隔(頻率)
	(1) freq: 重複的類型
			  YEARLY, MONTHLY, WEEKLY, DAILY, HOURLY, MINUTELY, SECONDLY
			  年,,,,    小時,   分鐘,(2) interval: 重複的間隔,默認爲 1, 取值範圍 1-99
		'freq = weekly; interval = 1': 每週執行一次   
	
5. enabled: 指定 job 創建完畢時, 是否自動激活

6. comments: 對於 job 的簡單說明

執行日誌:

SELECT to_char(t.log_date, 'YYYY-MM-DD HH24:MI:SS'), t.*
  FROM dba_scheduler_job_log t
 WHERE t.owner = 'SYSTEM' -- 測試用戶
   AND t.LOG_DATE >= DATE '2020-06-19' -- 測試時間
 ORDER BY t.log_date DESC;

在這裏插入圖片描述

方式2:dbms_scheduler.create_schedule + dbms_scheduler.create_program

BEGIN
   dbms_scheduler.create_schedule(schedule_name   => 'SYSTEM.TEST_SCHEDULE_NAME_O1', -- 唯一
                                  start_date      => SYSDATE, -- 開始執行時間,默認當前
                                  repeat_interval => 'FRQE = MINUTELY; INTERVAL = 1',
                                  end_date        => SYSDATE + 7, -- 執行結束時間,默認永久
                                  comments        => '每天執行'); -- 備註信息
END;
/

BEGIN
   dbms_scheduler.create_program(program_name   => 'SYSTEM.TEST_PROGRAME_NAME_01',
                                 program_type   => 'STORED_PROCEDURE', -- 同 job_type
                                 program_action => 'SYSTEM.P_SCHEDULER_TEST',
                                 enabled        => TRUE,
                                 comments       => '測試01');
END;
/

BEGIN
   dbms_scheduler.create_job(job_name            => 'SYSTEM.TEST_JOB_NAME_02',
                             program_name        => 'SYSTEM.TEST_PROGRAME_NAME_01', -- 引用 program
                             schedule_name       => 'SYSTEM.TEST_SCHEDULE_NAME_O1', -- 引用 schedule
                             enabled             => TRUE,
                             comments            => 'program + schedule 方式創建 job');
END;
/

2.2 修改

  • 活動的 job 才能被修改(已完成的改不了哦)
BEGIN
   dbms_scheduler.set_attribute(NAME      => 'SYSTEM.TEST_JOB_NAME_01',
                                attribute => 'end_date',
                                VALUE     => SYSDATE + 2 / (24 * 60));
END;

運行結果:(因爲這個任務已經完成了,所以無法被修改)
在這裏插入圖片描述

驗證:修改執行中 job 的屬性(如:end_date)

先清空表 test_job TRUNCATE TABLE test_job;,便於測試觀察

DECLARE

BEGIN
   dbms_scheduler.create_job(job_name        => 'SYSTEM.TEST_JOB_NAME_01',
                             job_type        => 'PLSQL_BLOCK',
                             job_action      => 'INSERT INTO test_job(job_name, start_date) VALUES(''TEST_JOB_NAME_01'', SYSDATE);',
                             start_date      => SYSDATE,
                             repeat_interval => 'freq = minutely; interval = 1',
                             -- end_date        => SYSDATE + 3 / (24 * 60), -- 註釋此處,方便修改
                             enabled         => TRUE,
                             comments        => '1 分鐘打印當前時間');
END;
/

等個幾分鐘,再執行上述修改屬性代碼:(dbms_scheduler.set_attribute)後測試結果:

SELECT * FROM test_job;

SELECT to_char(t.log_date, 'YYYY-MM-DD HH24:MI:SS'), t.*
  FROM dba_scheduler_job_log t
 WHERE t.owner = 'SYSTEM' -- 測試用戶
   AND t.LOG_DATE >= TO_DATE('2020/6/19 8:16:05', 'YYYY/MM/DD hh24:mi:ss') -- 測試時間
 ORDER BY t.log_date DESC;

在這裏插入圖片描述

2.3 刪除

DECLARE
BEGIN
   -- 其它的刪除類似,如 dbms_scheduler.drop_xxx();
   dbms_scheduler.drop_job(job_name => '', force => TRUE);
END;
/

2.4 查詢

SELECT * FROM dba_scheduler_jobs t; -- 查看 job 信息 (其中 AUTO_DROP: 是否自動刪除)
SELECT * FROM dba_scheduler_job_log t; -- 日誌
SELECT * FROM dba_scheduler_job_run_details t; -- 運行日誌
SELECT * FROM dba_scheduler_running_jobs t; -- 正在運行的 job

2.5 其它操作

-- 立即運行 job
dbms_scheduler.run_job('job_name');

-- 立即停止 job
dbms_scheduler.stop_job('job_name',FORCE);

-- 啓用 job
dbms_scheduler.enable('job_name');

-- 禁用 job
dbms_scheduler.disable('job_name', FORCE);

3 dbms_job

3.1 設置併發數

1. 查看數據庫中定時任務的最多併發數

> show parameter job_queue_processes

2. 設置數據庫中定時任務的最多併發數(比如:10)

> alter system set job_queue_processes = 10

3.2 job 調度任務查詢

SELECT t.* FROM dba_jobs t; -- 所有的 job
SELECT t.* FROM all_jobs t; -- 當前用戶所有能夠訪問的 job
SELECT t.* FROM user_jobs t; -- 當前用戶下

SELECT t.* FROM dba_jobs_running t; -- 執行中的 job

interval 參數說明:

1. 每天運行一次						'SYSDATE + 1'
2. 每小時運行一次					'SYSDATE + 1/24'
3.10 分鐘運行一次				'SYSDATE + 10/(24*60)'
4.30 秒運行一次					'SYSDATE + 30/(24*60*60)'
5. 每隔一個星期運行一次				'SYSDATE + 7' 
6. 不再運行該任務並刪除				NULL
7. 每天午夜 12'TRUNC(SYSDATE + 1)'
8. 每天早上 830'TRUNC(SYSDATE + 1) + (8*60+30)/(24*60)'
9. 每星期二中午 12'NEXT_DAY(TRUNC(SYSDATE), "TUSDAY") + 12/24'
10. 每個月第一天的午夜 12'TRUNC(LAST_DAT(SYSDATE) + 1)'
11. 每個季度最後一天的晚上 11'TRUNC(ADD_MONTHS(SYSDATE + 2/24, 3), "Q")' - 1/24
12. 每週六和週日早上 610'TRUNC(LEAST(NEXT_DAY(SYSDATE, "SATURDAY"), NEXT_DAY(SYSDATE), "SUNDAY")) + (6*60+10)/(24*60)'

3.3 常用操作

  • 道理和 dbms_scheduler 相同,而且 dbms_job 已不推薦使用,故此處知曉即可。
1. 提交 job
dbms_job.submit();

2. 啓動運行 job
dbms_job.run();

3. 刪除 job: 
dbms_job.remove(job);

4. 修改要執行的操作 job
dbms_job.what(job, what);

5. 修改下次執行時間
dbms_job.next_date(job, next_date)

6. 修改時間間隔
dbms_job.interval(job, interval);

7. 停止 job
dbms_job.broken(job, broken, next_date);
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章