Oracle定時任務(DBMS_Job)詳解

langgufu314發表於2011-09-23

 

對於DBA來說,資料庫Job在熟悉不過了,因為經常要資料庫定時的自動執行一些指令碼,或做資料庫備份,或做資料的提煉,或做資料庫的效能優化,包括重建索引等等的工作。但是,Oracle定時器Job時間的處理上,千變萬化,今天我把比較常用的寫法彙總如下:

    在總結之前,先把Job的引數一一說明一下:

    Job引數是有Submit()過程返回的binary_integer。

    what引數是將被執行的PL/SQL程式碼塊。

    next_date引數指何時將執行這個工作。寫Job的時候可以不指定該值。

    interval引數何時這個工作將被重執行

其中Interval這個值是決定Job何時,被重新執行的關鍵。

 

例如:有儲存過程p_dosomethings,需要被不同的時間間隔執行。

 

declare

    jobno number;

begin

    dbms_job.submit(

    jobno,

    'p_dosomething', --what

    to_date(), --next_date,可以不填

    'Interval時間字串' --interval,關鍵設定

    );

    commit;

end;

 

例如:

declare

JOB_ILEARN_ONLINE number :=1;

begin

dbms_job.submit(JOB_ILEARN_ONLINE,'insert into testdate(today) values(sysdate);',sysdate,'TRUNC(sysdate,''mi'') + 1 / (24*60)
');

commit;

end;

1、每分鐘執行

    Interval => TRUNC(sysdate, 'mi')+1/(24*60)

2、每天定時執行

    例如:每天的凌晨2點執行

    Interval => TRUNC(sysdate)+1+2/(24)

3、每週定時執行

    例如:每週一凌晨2點執行

    Interval => TRUNC(next_day(sysdate, 2))+2/24 --星期一,一週的第二天

4、每月定時執行

    例如:每月1日凌晨2點執行

    Interval => TRUNC(LAST_DAY(SYSDATE))+1+2/24

5、每季度定時執行

    例如每季度的第一天凌晨2點執行

    Interval => TRUNC(ADD_MONTH(SYSDATE), 3),'Q')+2/24

6、每半年定時執行

    例如:每年7月1日和1月1日凌晨2點

    Interval => ADD_MONTHS(trunc(sysdate,'yyyy'),6)+2/24

7、每年定時執行

    例如:每年1月1日凌晨2點執行

    Interval => ADD_MONTHS(trunc(sysdate,'yyyy'),12)+2/24

 

 

另一篇轉載自:http://wallimn.iteye.com/blog/519924

1.確保Oracle的工作模式允許啟動任務佇列管理器 
Oracle定時執行“Job Queue”的後臺程式是SNP程式,而要啟動SNP程式,首先要確保整個系統的模式是可以啟動SNP程式的,這需要以DBA的身份去執行如下命令: 
svrmgrl> alter system enable restricted session; 
或sql> alter system disenable restricted session; 
利用如上命令更改系統的會話方式為disenable restricted,為SNP的啟動創造條件。 

2.確保Oracle的系統已經配置了任務佇列管理器的啟動引數 
SNP的啟動引數位於Oracle的初始化檔案中,該檔案放在$ORACLE_HOME/dbs路徑下,如果Oracle的SID是myora8的話,則初始化檔案就是initmyora8.ora,在檔案中對SNP啟動引數的描述部分如下: 

job_queue_process=n 
job_queue_interval=N 

第一行定義SNP程式的啟動個數為n。系統預設值為0,正常定義範圍為0~36,根據任務的多少,可以配置不同的數值。 

第二行定義系統每隔N秒喚醒該程式一次。系統預設值為60秒,正常範圍為1~3600秒。事實上,該程式執行完當前任務後,就進入睡眠狀態,睡眠一段時間後,由系統的總控負責將其喚醒。 
如果該檔案中沒有上面兩行,請按照如上配置新增。配置完成後,需要重新啟動資料庫,使其生效。注意:如果任務要求執行的間隔很短的話,N的配置也要相應地小一點。 

3.將任務加入到資料庫的任務佇列中 
呼叫Oracle的dbms_job包中的儲存過程,將任務加入到任務佇列中: 
dbms_job.submit( job out binary_integer, 
what       in   archar2, 
next_date     in   date, 
interval     in   varchar2, 
no_parse     in   boolean) 

其中: 
●job:輸出變數,是此任務在任務佇列中的編號; 
●what:執行的任務的名稱及其輸入引數; 
●next_date:任務執行的時間; 
●interval:任務執行的時間間隔。 

    下面詳細討論一下dbms_job.submit中的引數interval。嚴格地講,interval是指上一次執行結束到下一次開始執行的時間間隔,當interval設定為null時,該job執行結束後,就被從佇列中刪除。假如我們需要該job週期性地執行,則要用‘sysdate+m’表示。  

    將任務加入到任務佇列之前,要確定執行任務的資料庫使用者,若使用者是scott, 則需要確保該使用者擁有執行包dbms_job的許可權;若沒有,需要以DBA的身份將權利授予scott使用者: 
svrmgrl> grant execute on dbms_job to scott; 

4.將要執行的任務寫成儲存過程或其他的資料庫可執行的pl/sql程式段 
例如,我們已經建立了一個儲存過程,其名稱為my_job,在sql/plus中以scott使用者身份登入,執行如下命令: 
sql> variable n number; 
sql> begin 
dbms_job.submit(:n‘my_job;’,sysdate, 
‘sysdate+1/360’); 
commit; 
end; 
/ 
系統提示執行成功。 

Sql> print :n; 
系統列印此任務的編號,例如結果為300。 

    如上,我們建立了一個每隔4分鐘執行一次的任務號為300的任務。可以通過Oracle提供的資料字典user_jobs察看該任務的執行情況: 
sql> select job,next_date,next_sec,failures,broken from user_jobs; 
執行結果如下: 
job next_date next_sec failures broken 
300 2000/10/10 11:45:15 0 N 

    這表示任務號為300的任務,下一次將在2000/10/10 11:45:15執行,此任務的執行失敗記錄為0次。注意:當執行job出現錯誤時,Oracle將其記錄在日誌裡,失敗次數每次自動加1。當執行失敗次數達到16時,Oracle就將該job標誌為broken。此後,Oracle不再繼續執行它,直到使用者呼叫過程dbms_job.broken,重新設定為not broken,或強制呼叫dbms_job.run來重新執行它。 

   除了以上我們討論的submit儲存過程之外,Oracle還提供了其他許多儲存過程來操作任務。例如:dbms_job.change 、 dbms_job.what、dbms_job.interval可以用來修改提交的任務。要想刪除該任務,只需執行dbms_job.remove(n)即可,其中n為任務號。 

========================================================================= 

一個簡單例子: 
1、建立測試表 
SQL> create table a(a date); 

表已建立。 

2、建立一個自定義過程 
SQL> create or replace procedure test as 
2 begin 
3 insert into a values(sysdate); 
4 end; 
5 / 

過程已建立。 

3、建立JOB 
SQL> variable job1 number; 
SQL> 
SQL> begin 
2 dbms_job.submit(:job1,'test;',sysdate,'sysdate+1/1440');  --每天1440分鐘,即一分鐘執行test過程一次 
3 COMMIT; 
4 end; 
5 / 

PL/SQL 過程已成功完成。 

4、執行JOB 
SQL> begin 
2 dbms_job.run(:job1); 
3 end; 
4 / 

PL/SQL 過程已成功完成。 

SQL> select to_char(a,'yyyy/mm/dd hh24:mi:ss') 時間 from a; 

時間 
------------------- 
2001/01/07 23:51:21 
2001/01/07 23:52:22 
2001/01/07 23:53:24 

5、修改下次執行時間(10分鐘後執行) 
SQL>begin 
2 dbms_job.next_date (:job1,SYSDATE + 10/(24*60)); 
3 end; 
4 / 

6、刪除JOB 
SQL> begin 
2 dbms_job.remove(:job1); 
3 end; 
4 / 

PL/SQL 過程已成功完成。 

************************************************* 

DBMS_Job包含以下子過程: 
  Broken()過程。 
  change()過程。 
  Interval()過程。 
  Isubmit()過程。 
  Next_Date()過程。 
  Remove()過程。 
  Run()過程。 
  Submit()過程。 
  User_Export()過程。 
  What()過程。 

1、Broken()過程更新一個已提交的工作的狀態,典型地是用來把一個已破工作標記為未破工作。這個過程有三個引數:job 、broken與next_date。 
PROCEDURE Broken ( 
job IN binary_integer, 
Broken IN boolean, 
next_date IN date :=SYSDATE 
) 

job引數是工作號,它在問題中唯一標識工作。 
broken引數指示此工作是否將標記為破——TRUE說明此工作將標記為破,而FLASE說明此工作將標記為未破。 
next_date引數指示在什麼時候此工作將再次執行。此引數預設值為當前日期和時間。 

2、Change()過程用來改變指定工作的設定。 
這個過程有四個引數:job、what 、next_date與interval。 
PROCEDURE Change ( 
job IN binary_integer, 
What IN varchar2, 
next_date IN date, 
interval IN varchar2) 

此job引數是一個整數值,它唯一標識此工作。 
What引數是由此工作執行的一塊PL/SQL程式碼塊。 
next_date引數指示何時此工作將被執行。 
interval引數指示一個工作重執行的頻度。 

3、Interval()過程用來顯式地設定重執行一個工作之間的時間間隔數。 
這個過程有兩個引數:job與interval。 
PROCEDURE Interval ( 
job IN binary_integer, 
Interval IN varchar2) 

job引數標識一個特定的工作。 
interval引數指示一個工作重執行的頻度。 

4、ISubmit()過程用來用特定的工作號提交一個工作。 
這個過程有五個引數:job、what、next_date、interval與no_parse。 
PROCEDURE ISubmit ( 
job IN binary_ineger, 
What IN varchar2, 
next_date IN date, 
interval IN varchar2, 
no_parse IN booean:=FALSE) 
這個過程與Submit()過程的唯一區別在於此job引數作為IN型引數傳遞且包括一個由開發者提供的工作號。如果提供的工作號已被使用,將產生一個錯誤。 

5、Next_Date()過程用來顯式地設定一個工作的執行時間。這個過程接收兩個引數:job與next_date。 
PROCEDURE Next_Date( 
job IN binary_ineger, 
next_date IN date) 

job標識一個已存在的工作。 
next_date引數指示了此工作應被執行的日期與時間。 

6、Remove()過程來刪除一個已計劃執行的工作。這個過程接收一個引數: 
PROCEDURE Remove(job IN binary_ineger); 

job引數唯一地標識一個工作。這個引數的值是由為此工作呼叫Submit()過程返回的job引數的值。已正在執行的工作不能由呼叫過程式刪除。 

7、Run()過程用來立即執行一個指定的工作。這個過程只接收一個引數: 
PROCEDURE Run(job IN binary_ineger) 

job引數標識將被立即執行的工作。 

8、使用Submit()過程,工作被正常地計劃好。 
這個過程有五個引數:job、what、next_date、interval與no_parse。 
PROCEDURE Submit ( 
job OUT binary_ineger, 
What IN varchar2, 
next_date IN date, 
interval IN varchar2, 
no_parse IN booean:=FALSE) 

job引數是由Submit()過程返回的binary_ineger。用來唯一標識一個工作。 
what引數是將被執行的PL/SQL程式碼塊。 
next_date引數指識何時將執行這個工作。 
interval引數何時這個工作將被重執行。 
  dbms_job.submit(:job1,'test;',sysdate,'sysdate+1/1440');   
    sysdate+1/1440:每天1440分鐘,即一分鐘執行test過程一次 
    TRUNC(SYSDATE+1)+10/24:每天上午10點、晚上10點執行一次 
no_parse引數指示此工作在提交時或執行時是否應進行語法分析——TRUE 
指示此PL/SQL程式碼在它第一次執行時應進行語法分析, 
而FALSE指示本PL/SQL程式碼應立即進行語法分析。 

9、User_Export()過程返回一個命令,此命令用來安排一個存在的工作以便此工作能重新提交。此程式有兩個引數:job與my_call。 
PROCEDURE User_Export( 
job IN binary_ineger, 
my_call IN OUT varchar2) 

job引數標識一個安排了的工作。 
my_call引數包含在它的當前狀態重新提交此工作所需要的正文。 

10、What()過程應許在工作執行時重新設定此正在執行的命令。這個過程接收兩個引數:job與what。 

PROCEDURE What ( 
job IN binary_ineger, 
What IN OUT varchar2) 

job引數標識一個存在的工作。 
what引數指示將被執行的新的PL/SQL程式碼。 

============================================================= 

-- ------------------------------------------------------------ 
-- 提交任務從6:00開始,每小時執行一次 
-- ------------------------------------------------------------ 

dbms_job.submit( 
jobno, 'statspack.snap;', 
trunc(sysdate)+6/24, 
'trunc(SYSDATE+1/24,''HH'')', 
TRUE, 
instno); 
-- ------------------------------------------------------------ 
-- 提交任務從9:00開始,12小時後執行 
-- ------------------------------------------------------------ 
dbms_job.submit( 
jobno, 
'statspack.snap;', 
trunc(sysdate+1)+9/24, 
'trunc(SYSDATE+12/24,''HH'')', 
TRUE, 
instno); 
------------------------------------------------------------ 
-- 提交任務從6:00開始,每隔十分鐘執行一次 
-- ------------------------------------------------------------ 

dbms_job.submit( 
jobno, 
'statspack.snap;', 
trunc(sysdate+1/144,'MI'), 
'trunc(sysdate+1/144,''MI'')', 
TRUE, 
instno); 
-- ---------------------------------------------------------------- 
-- 提交任務從週一到週五早上6:00開始,每小時執行一次 
-- ---------------------------------------------------------------- 
dbms_job.submit( 
jobno, 
'statspack.snap;', 
trunc(sysdate+1)+6/24, 
'trunc( 
least( 
next_day(SYSDATE,''MONDAY''), 
next_day(SYSDATE,''TUESDAY''), 
next_day(SYSDATE,''WEDNESDAY''), 
next_day(SYSDATE,''THURSDAY''), 
next_day(SYSDATE,''FRIDAY'') 
) 
+1/24,''HH'')', 
TRUE, 
instno); 
commit; 
end;

相關文章