天天看點

ORACLE JOB建立及使用詳解

Oracle job有定時執行的功能,可以在指定的時間點或每天的某個時間點自行執行任務。

一、查詢系統中的job,可以查詢視圖

--相關視圖

select * from dba_jobs;

select * from all_jobs;

select * fromuser_jobs;

-- 查詢字段描述

/*

字段(列) 類型 描述

JOB NUMBER 任務的唯一标示号

LOG_USER VARCHAR2(30) 送出任務的使用者

PRIV_USER VARCHAR2(30) 賦予任務權限的使用者

SCHEMA_USER VARCHAR2(30) 對任務作文法分析的使用者模式

LAST_DATE DATE 最後一次成功運作任務的時間

LAST_SEC VARCHAR2(8) 如HH24:MM:SS格式的last_date日期的小時,分鐘和秒

THIS_DATE DATE 正在運作任務的開始時間,如果沒有運作任務則為null

THIS_SEC VARCHAR2(8) 如HH24:MM:SS格式的this_date日期的小時,分鐘和秒

NEXT_DATE DATE 下一次定時運作任務的時間

NEXT_SEC VARCHAR2(8) 如HH24:MM:SS格式的next_date日期的小時,分鐘和秒

TOTAL_TIME NUMBER 該任務運作所需要的總時間,機關為秒

BROKEN VARCHAR2(1) 标志參數,Y标示任務中斷,以後不會運作

INTERVAL VARCHAR2(200) 用于計算下一運作時間的表達式

FAILURES NUMBER 任務運作連續沒有成功的次數

WHAT VARCHAR2(2000) 執行任務的PL/SQL塊

CURRENT_SESSION_LABELRAW MLSLABEL 該任務的信任Oracle會話符

CLEARANCE_HI RAW MLSLABEL 該任務可信任的Oracle最大間隙

CLEARANCE_LO RAW MLSLABEL 該任務可信任的Oracle最小間隙

NLS_ENV VARCHAR2(2000) 任務運作的NLS會話設定

MISC_ENV RAW(32) 任務運作的其他一些會話參數

*/

-- 正在運作job

select * fromdba_jobs_running;

其中最重要的字段就是job這個值就是我們操作job的id号,what 操作存儲過程的名稱,next_date 執行的時間,interval執行間隔

二、執行間隔interval運作頻率

描述 INTERVAL參數值

每天午夜12點 TRUNC(SYSDATE + 1)

每天早上8點30分 TRUNC(SYSDATE + 1) +(860+30)/(2460)

每星期二中午12點 NEXT_DAY(TRUNC(SYSDATE ),''TUESDAY'' ) + 12/24

每個月第一天的午夜12點 TRUNC(LAST_DAY(SYSDATE ) + 1)

每個季度最後一天的晚上11點 TRUNC(ADD_MONTHS(SYSDATE + 2/24, 3 ), 'Q') -1/24

每星期六和日早上6點10分 TRUNC(LEAST(NEXT_DAY(SYSDATE,''SATURDAY"), NEXT_DAY(SYSDATE, "SUNDAY"))) + (6×60+10)/(24×60)

每秒鐘執行次 Interval => sysdate+ 1/(24 60 60)

如果改成sysdate + 10/(24 60 60)就是10秒鐘執行次

每分鐘執行

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

如果改成TRUNC(sysdate,'mi')+ 10/ (24*60) 就是每10分鐘執行次

每天定時執行

每周定時執行

每月定時執行

每季度定時執行

每半年定時執行

每年定時執行

三、建立job方法

建立job,基本文法:

declare

begin

end;

使用dbms_job.submit方法過程,這個過程有五個參數:job、what、next_date、interval與no_parse。

dbms_job.submit(

job OUT binary_ineger,

What IN varchar2,

next_date IN date,

interval IN varchar2,

no_parse IN booean:=FALSE)

job參數是輸出參數,由submit()過程傳回的binary_ineger,這個值用來唯一辨別一個工作。一般定義一個變量接收,可以去user_jobs視圖查詢job值。

what參數是将被執行的PL/SQL代碼塊,存儲過程名稱等。

next_date參數指識何時将運作這個工作。

interval參數何時這個工作将被重執行。

no_parse參數訓示此工作在送出時或執行時是否應進行文法分析——true,預設值false。訓示此PL/SQL代碼在它第一次執行時應進行文法分析,而FALSE訓示本PL/SQL代碼應立即進行文法分析。

四、其他job相關的存儲過程

大緻介紹下這些過程:

1、broken()過程更新一個已送出的工作的狀态,典型地是用來把一個已破工作标記為未破工作。這個過程有三個參數:job、broken與next_date。

job參數是工作号,它在問題中唯一辨別工作。

broken參數訓示此工作是否将标記為破——true說明此工作将标記為破,而false說明此工作将标記為未破。

next_date參數訓示在什麼時候此工作将再次運作。此參數預設值為目前日期和時間。

job如果由于某種原因未能成功執行,oracle将重試16次後,還未能成功執行,将被标記為broken,重新啟動狀态為broken的job,有如下兩種方式;

a、利用dbms_job.run()立即執行該job

b、利用dbms_job.broken()重新将broken标記為false

2、change()過程用來改變指定job的設定。

這個過程有四個參數:job、what、next_date、interval。

這裡,

job參數是一個整數值,它唯一辨別此工作。

what參數是由此job運作的一塊PL/SQL代碼塊。

next_date參數訓示何時此job将被執行。

interval參數訓示一個job重執行的頻度。

3、interval()過程用來顯式地設定重複執行一個job之間的時間間隔數。

這個過程有兩個參數:job、interval。

job參數辨別一個特定的工作。

interval參數訓示一個工作重執行的頻度。

4、isubmit()過程用來用特定的job号送出一個job。

這個過程有五個參數:job、what、next_date、interval、no_parse。

這個過程與submit()過程的唯一差別在于此job參數作為IN型參數傳遞且包括一個由開發者提供的job号。如果提供的job号已被使用,将産生一個錯誤。

5、next_date()過程用來顯式地設定一個job的執行時間。這個過程接收兩個參數:job、next_date。

job辨別一個已存在的工作。

next_date參數訓示了此job應被執行的日期、時間。

6、remove()過程來删除一個已計劃運作的job。這個過程接收一個參數:

job參數唯一地辨別一個工作這個參數的值是由為此工作調用submit()過程傳回的job參數的值,已正在運作的job不能删除。

7、run()過程用來立即執行一個指定的job。這個過程隻接收一個參數:

procedure run(job INbinary_ineger)

job參數辨別将被立即執行的工作。

8、使用submit()過程,job被正常地計劃。

9、user_export()過程傳回一個指令,此指令用來安排一個存在的job以便此job能重新送出。此程式有兩個參數:job、my_call。

procedure user_export(

)

job參數辨別一個安排了的工作。

my_call參數包含在它的目前狀态重新送出此job所需要的正文。

10、what()過程應許在job執行時重新設定此正在運作的指令。這個過程接收兩個參數:job、what。

job參數辨別一個存在的工作。

what參數訓示将被執行的新的PL/SQL代碼。實作的功能:每隔一分鐘自動向getSysDate表中插入目前的系統時間。

五、示例

/ 每10秒鐘執行一次 插入一條時間 /

-- 建立table

-- 建立存儲過程

as

-- 調用過程測試

--select 24 60 60 from dual; --得出一天的秒數

-- 建立job

-- 運作job

-- 查詢是否插入資料

-- 删除一個job

六、關于設定job任務數量和控制并發

初始化相關參數job_queue_processes

job_queue_process表示oracle能夠并發的job的數量,sqlplus中可以通過語句

show parameterjob_queue_process; 來檢視oracle中job_queue_process的值。

select * fromv$parameter;

select name,description from v$bgprocess;

七、job不運作的大概原因

(1)、上面講解了job的參數:與job相關的參數一個是job_queue_processes,這個是運作job時候所起的程序數,當然系統裡面job大于這個數值後,就會有排隊等候的,最小值是0,表示不運作job,最大值是1000,在OS上對應的程序時SNPn,9i以後OS上管理job的程序叫CJQn。可以使用下面這個SQL确定目前有幾個SNP/CJQ在運作。

select * fromv$bgprocess,這個paddr不為空的snp/cjq程序就是目前空閑的程序,有的表示正在工作的程序。

另外一個是job_queue_interval,範圍在1--3600之間,機關是秒,這個是喚醒JOB的process,因為每次snp運作完他就休息了,需要定期喚醒他,這個值不能太小,太小會影響資料庫的性能。

先确定上面這兩個參數設定是否正确,特别是第一個參數,設定為0了,所有job就不會自動運作了。

(2)、使用下面的SQL檢視job的的broken,last_date和next_date,last_date是指最近一次job運作成功的結束時間,next_date是根據設定的頻率計算的下次執行時間,根據這個資訊就可以判斷job上次是否正常,還可以判斷下次的時間對不對,SQL如下:

有時候我們發現他的next_date是4000年1月1日,說明job要不就是在running,要不就是狀态是break(broken=Y),如果發現job的broken值為Y,找使用者了解一下,确定該job是否可以broken,如果不能broken,那就把broken值修改成N,修改再使用上面的SQL檢視就發現它的last_date已經變了,job即可正常運作,修改broken狀态的SQL如下:

(3)、使用下面的SQL查詢是否job還在running

如果發現job已經Run了很久了還沒有結束,就要查原因了。一般的jobrunning時會鎖定相關的相關的資源,可以檢視一下v$access和v$locked_object這兩個view。如果發現其他程序鎖定了與job相關的object,包括package/function/procedure/table等資源,那麼就要把其他程序删除,有必要的話,把job的程序也删除,再重新執行看看結果。

(4)、如果上面都正常,但是job還不run,怎麼辦?那我們要考慮把job程序重新開機一次,防止是SNP程序死了造成job不跑,指令如下:

alter system setjob_queue_processes = 0; --關閉job程序,等待5--10秒鐘

alter system setjob_quene_processes = 5; --恢複原來的值

(5)、Oracle的BUG:Oracle9i裡面有一個BUG,當計數器到497天時,剛好達到它的最大值,再計數就會變成-1,繼續計數就變成0了,然後計數器将不再跑了。如果碰到這種情況就得重新開機資料庫,但是其他的Oracle7345和Oracle8i的資料庫沒有發現這個問題。

(6)、資料庫上的檢查基本上就這多,如果job運作還有問題,那需要看一下是否是程式本身的問題,比如處理的資料量大,或者網絡速度慢等造成運作時過長,那就需要具體情況具體分析了。我們可以通過下面的SQL手工執行一下job看看:

JOB鎖處理方法:

找出正在執行的JOB編号及其會話編号

  SELECT SID,JOB FROM DBA_JOBS_RUNNING;

  停止該JOB的執行

  SELECT SID,SERIAL# FROM V$SESSION WHERE SID='&SID';

  ALTER SYSTEM KILL SESSION '&SID,&SERIAL';

  EXEC DBMS_JOB.BROKEN(&JOB,TRUE);

  執行個體分析:

  1,查詢正在運作的Job,通過查詢有兩個,和程序占用較多的是兩個Oracle程序符合。

  SQL> SELECT SID,JOB FROM DBA_JOBS_RUNNING;

  SID JOB

  ---------- ----------

  12 116

  16 117

  2,查詢正在運作的job的資訊

  SQL> SELECT SID,SERIAL# FROM V$SESSION WHERE SID='12';

  SID SERIAL#

  12 4

  SQL> SELECT SID,SERIAL# FROM V$SESSION WHERE SID='16';

  16 1

  3,利用查詢出來的job資訊将job結束掉

  SQL> ALTER SYSTEM KILL SESSION '12,4';

  System altered.

  SQL> ALTER SYSTEM KILL SESSION '16,1';

  4,如果不希望運作上述job的話,可以将job設定為broken.

  EXEC DBMS_JOB.BROKEN(116,TRUE);

  EXEC DBMS_JOB.BROKEN(117,TRUE);

  根據個人經驗,這種方法并不會立即中斷job的運作。最好是找到job對應的線程kill掉。

删除JOB方法:注:BROKEN值如果為TRUE則為停用,FALSE為啟用,預設FALSE。

DBMS_JOB.BROKEN(JOB編号,TRUE);

dbms_job.remove(JOB編号);

commit;