一點一點學習jobs的各個方面比較長,比較煩,但是應該看完后會對jobs比較好的應用
一、學習准備
開始dbms_job學習前,先認識一個參數job_queue_processes
a、job_queue_processes參數決定了job作業能夠使用的總進程數。
b、當該參數為0值,任何job都不會被執行,建議合理設置該值且至少大於1。
c、對於job運行時間也應該盡量合理的設置間隔以及啟動時間。
d、如果同一時間內運行的Job數很多,過小的參數值導致job不得不進行等待。而過大的參數值則消耗更多的系統資源。
f、對於存在依賴關系的job,盡可能將其進行合並到一個job中,如使用chain等。
想細致了解的請前往
http://blog.csdn.net/robinson_0612/article/details/8694772
在使用dbms_jobs時首先確認job_queue_processes的值(10g系統默認為10)
SQL> SHOW PARAMETER JOB_QUEUE_PROCESSES; NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ job_queue_processes integer 10
另外10g開始提供了一個新的job管理包:DBMS_SCHEDULER
http://space.itpub.net/8858072/viewspace-425547
http://www.cnblogs.com/lanzi/archive/2012/11/23/2784815.html
二、創建第一個job
SQL> create table a(a date); Table created. SQL> create or replace procedure job_test as 2 begin 3 insert into a values(sysdate); 4 end; 5 / Procedure created. SQL> exec job_test; PL/SQL procedure successfully completed. SQL> select * from a; A ------------------- 2013-05-31 15:45:32
創建一個job任務,時間間隔為每秒一次
SQL>variable job1 number;--注意別漏了定義變量 SQL> begin 2 dbms_job.submit(:job1,'job_test;',sysdate,'sysdate+1/64800'); 3 commit; 4 end; 5 / PL/SQL procedure successfully completed
也可以更清晰的使用這個方式建立job
variable job1 number; begin sys.dbms_job.submit(job => :job1, what => 'job_test;', next_date => sysdate, interval => 'sysdate+1/64800');--每天64800秒,即每秒執行一次,但是實際oracle的jobs不能精確到秒,這里只是為了快速測試效果 commit; end;
SQL> select job,to_char(next_date,'yyyy-mm-dd hh24:mi:ss') as n_date,what,interval,broken from user_jobs; JOB N_DATE WHAT INTERVAL B ---------- ------------------- ---------- -------------------- - 4 2013-05-31 15:49:24 job_test; sysdate+1/64800 N SQL> select count(*) from a; COUNT(*) ---------- 9 SQL> / COUNT(*) ---------- 10 SQL> / COUNT(*) ---------- 10 SQL> select * from a; A ------------------- 2013-05-31 15:45:32 2013-05-31 15:48:58 2013-05-31 15:49:03 2013-05-31 15:49:08 2013-05-31 15:49:13 2013-05-31 15:49:18 2013-05-31 15:49:23 2013-05-31 15:49:28 2013-05-31 15:49:33 2013-05-31 15:49:38 2013-05-31 15:49:43 11 rows selected.
從實際執行結果看,秒級的任務並非按每秒執行,間隔在2-5秒間,原因位置,平時秒級的任務需求也沒有,不做深入研究
三、修改job執行間隔
SQL> exec dbms_job.change(4,null,null,'sysdate+1/1440'); PL/SQL procedure successfully completed. SQL> commit; --一定要記得commit否則重啟后會丟失 Commit complete. SQL> select job,to_char(next_date,'yyyy-mm-dd hh24:mi:ss') as n_date,what,interval,broken from user_jobs; JOB N_DATE WHAT INTERVAL B ---------- ------------------- ---------- -------------------- - 4 2013-05-31 15:57:08 job_test; sysdate+1/1440 N SQL> truncate table a; Table truncated. SQL> select * from a; no rows selected SQL> select * from a; A ------------------- 2013-05-31 15:57:08 SQL> / A ------------------- 2013-05-31 15:57:08 2013-05-31 15:58:08 2013-05-31 15:59:08 2013-05-31 16:00:08 2013-05-31 16:01:08
修改成功
但是有瑕疵,08秒,假如我想精確,可以通過oracle的trunc函數(最后實驗結果告訴我trunc可以輸出00秒,但是jobs不能精確到秒)
SQL> alter session set nls_date_format='YYYY-MM-DD HH24:MI:SS'; Session altered. SQL> select sysdate from dual; SYSDATE ------------------- 2013-05-31 16:02:25 SQL> select trunc(sysdate,'mi') from dual; TRUNC(SYSDATE,'MI') ------------------- 2013-05-31 16:02:00
再次修改job
SQL> exec dbms_job.change(4,null,null,'trunc(sysdate,''mi'')+1/1440'); PL/SQL procedure successfully completed. SQL> commit; SQL> select job,to_char(next_date,'yyyy-mm-dd hh24:mi:ss') as n_date,what,interval,broken from user_jobs; JOB N_DATE WHAT INTERVAL B ---------- ------------------- ---------- -------------------- - 4 2013-05-31 16:12:00 job_test; trunc(sysdate,'mi')+ N 1/1440 SQL> select * from a; ..... A ------------------- 2013-05-31 16:08:09 2013-05-31 16:09:09 2013-05-31 16:10:09 2013-05-31 16:11:09 2013-05-31 16:12:04 2013-05-31 16:13:04 2013-05-31 16:14:04 2013-05-31 16:15:04 2013-05-31 16:16:04 2013-05-31 16:17:04 2013-05-31 16:18:04
還是不完美,繼續證實精確到秒的job無法實現--至少我測試結果如此
關於trunc的詳細使用,可以參考后面第六小節
四、臨時停止jobs
SQL> select job,to_char(next_date,'yyyy-mm-dd hh24:mi:ss') as n_date,what,interval,broken from user_jobs; JOB N_DATE WHAT INTERVAL B ---------- ------------------- ---------- -------------------- - 4 2013-05-31 16:12:00 job_test; trunc(sysdate,'mi')+ N 1/1440 SQL> exec dbms_job.broken(4,true); PL/SQL procedure successfully completed. SQL> commit; Commit complete. SQL> select job,to_char(next_date,'yyyy-mm-dd hh24:mi:ss') as n_date,what,interval,broken from user_jobs; JOB N_DATE WHAT INTERVAL B ---------- ------------------- ---------- -------------------- - 4 4000-01-01 00:00:00 job_test; trunc(sysdate,'mi')+ Y 1/1440
重新開始job
SQL> exec dbms_job.broken(4,false); PL/SQL procedure successfully completed. SQL> commit; Commit complete. SQL> select job,to_char(next_date,'yyyy-mm-dd hh24:mi:ss') as n_date,what,interval,broken from user_jobs; JOB N_DATE WHAT INTERVAL B ---------- ------------------- ---------- -------------------- - 4 2013-05-31 16:36:24 job_test; trunc(sysdate,'mi')+ N 1/1440
五、刪除jobs
SQL> exec dbms_job.remove(4); PL/SQL procedure successfully completed. SQL> select job,to_char(next_date,'yyyy-mm-dd hh24:mi:ss') as n_date,what,interval,broken from user_jobs; no rows selected SQL> rollback;--不commit咱rollback看看 Rollback complete. SQL> select job,to_char(next_date,'yyyy-mm-dd hh24:mi:ss') as n_date,what,interval,broken from user_jobs; JOB N_DATE WHAT INTERVAL B ---------- ------------------- ---------- -------------------- - 4 2013-05-31 16:36:24 job_test; trunc(sysdate,'mi')+ N 1/1440 --jobs又回來了 SQL> exec dbms_job.remove(4); PL/SQL procedure successfully completed. SQL> commit; Commit complete. SQL> select job,to_char(next_date,'yyyy-mm-dd hh24:mi:ss') as n_date,what,interval,broken from user_jobs; no rows selected --commit后就真的沒了
誤刪除后可以恢復所以記得正常刪除需要commit
六、jobs的間隔設置之日期函數學習
如果jobs跟linux crontab那樣 * * * * * 會覺得很時間設置很清晰
oracle感覺煩點
6.1 trunc()
先認識一個函數trunc()
這里只討論trunc的date相關
語法:
TRUNC (datetime_exp, fmt)
其中:
date 一個表達式,該表達式標識一個日期和時間數。
fmt 日期格式,該日期將由指定的元素格式所截去。忽略它則由最近的日期截去
以下是一些常用的日期格式范例
1)SQL> select trunc(sysdate) from dual ; --返回當前日期,精確到凌晨0點0分 TRUNC(SYSDATE) ------------------- 2013-06-04 00:00:00 2)SQL> select trunc(sysdate, 'mm') from dual;--mm格式為返回當月第一天 TRUNC(SYSDATE,'MM') ------------------- 2013-06-01 00:00:00 3)SQL> select trunc(sysdate,'yy') from dual;--yy格式,返回當年第一天 TRUNC(SYSDATE,'YY') ------------------- 2013-01-01 00:00:00 4)SQL> select trunc(sysdate,'dd') from dual; --dd返回當前年月日,與trunc(sysdate)等效 TRUNC(SYSDATE,'DD') ------------------- 2013-06-04 00:00:00 5)SQL> select trunc(sysdate,'yyyy') from dual; --yy跟yy一樣,返回當年第一天 TRUNC(SYSDATE,'YYYY ------------------- 2013-01-01 00:00:00 6)SQL> select trunc(sysdate,'d') from dual; --d返回本周第一天,按老美的,第一天是周日 TRUNC(SYSDATE,'D') ------------------- 2013-06-02 00:00:00 7)SQL> select trunc(sysdate, 'hh') from dual ; --hh返回當前時間,精確到 TRUNC(SYSDATE,'HH') ------------------- 2013-06-04 16:00:00 8)SQL> select trunc(sysdate, 'mi') from dual; --mi返回當前時間精確到分鍾,TRUNC()函數沒有秒的精確 TRUNC(SYSDATE,'MI') ------------------- 2013-06-04 16:29:00
再來幾個函數
last_day,next_day,add_months
6.2 last_day
返回指定時間當月的最后一天
SQL> select last_day('2013-10-5') from dual; LAST_DAY('2013-10-5 ------------------- 2013-10-31 00:00:00 SQL> select last_day(sysdate) from dual; LAST_DAY(SYSDATE) ------------------- 2013-06-30 18:16:30 想要下個月的3號 SQL> select last_day(sysdate)+3 from dual; LAST_DAY(SYSDATE)+3 ------------------- 2013-07-03 18:17:26 再組合下trunc SQL> select trunc(last_day(sysdate)+3) from dual; TRUNC(LAST_DAY(SYSD ------------------- 2013-07-03 00:00:00 再組合一個小時分鍾 SQL> select trunc(last_day(sysdate)+3)+3/24+30/1440 from dual; TRUNC(LAST_DAY(SYSD ------------------- 2013-07-03 03:30:00
n/24表示小時
n/1440表示分鍾
n/64800表示秒
6.3 next_day
返回下一個星期某一天
next_day(date,n)
想要每周3早上3點
SQL> select next_day(sysdate,4) from dual;--按老美的每周第一天是周日,所以周三是4 NEXT_DAY(SYSDATE,4) ------------------- 2013-06-05 18:22:59
組合下trunc、小時、分鍾
SQL> select trunc(next_day(sysdate,4))+3/24+30/1440 from dual; TRUNC(NEXT_DAY(SYSD ------------------- 2013-06-05 03:30:00
6.4 add_months
返回指定日期后的多少個月
add_months(date,n)
以當前日期為起始,每2個月后的今天的3:30
SQL> select trunc(add_months(sysdate,2))+3/24+30/1440 from dual; TRUNC(ADD_MONTHS(SY ------------------- 2013-08-04 03:30:00 SQL> select trunc(add_months(trunc(sysdate,'yy'),2))+3/24+30/1440 from dual; TRUNC(ADD_MONTHS(TR ------------------- 2013-03-01 03:30:00
也可以簡單點具體到每2個月那一天
SQL> select trunc(add_months('2013-01-03',2))+3/24+30/1440 from dual; TRUNC(ADD_MONTHS('2 ------------------- 2013-03-03 03:30:00
有了上面的基礎后我們來制定一些計划任務
6.5 來個需求試試
每月3號10:00執行job_test任務
SQL> variable job1 number; SQL> begin 2 dbms_job.submit(:job1,'job_test;',sysdate,'trunc(last_day(sysdate)+3)+3/24+30/1440'); 3 commit; 4 end; 5 / PL/SQL procedure successfully completed. SQL> set linesize 200 SQL> col job format 999 SQL> col what format a50 SQL> col interval format a50 SQL> col next_date format a50 SQL> select job,what,interval,to_char(next_date,'yyyy-mm-dd hh24:mi:ss') from user_jobs; JOB WHAT INTERVAL TO_CHAR(NEXT_DATE,' ---- -------------------------------------------------- -------------------------------------------------- ------------------- 8 job_test; trunc(last_day(sysdate)+3)+3/24+30/1440 2013-07-03 03:30:00
每周3凌晨3:30執行 job_test
SQL> variable job1 number; SQL> begin 2 dbms_job.submit(:job1,'job_test;',sysdate,'trunc(next_day(sysdate,4))+3/24+30/1440'); 3 commit; end; 4 5 / PL/SQL procedure successfully completed. SQL> SQL> select job,what,interval,to_char(next_date,'yyyy-mm-dd hh24:mi:ss') from user_jobs; JOB WHAT INTERVAL TO_CHAR(NEXT_DATE,' ---- -------------------------------------------------- -------------------------------------------------- ------------------- 8 job_test; trunc(last_day(sysdate)+3)+3/24+30/1440 2013-07-03 03:30:00 9 job_test; trunc(next_day(sysdate,4))+3/24+30/1440 2013-06-05 03:30:00
每天3點
SQL> variable job1 number; SQL> begin 2 dbms_job.submit(:job1,'job_test;',sysdate,'trunc(sysdate+1)+3/24'); 3 commit; 4 end; 5 / PL/SQL procedure successfully completed. SQL> select job,what,interval,to_char(next_date,'yyyy-mm-dd hh24:mi:ss') from user_jobs; JOB WHAT INTERVAL TO_CHAR(NEXT_DATE,' ---- -------------------------------------------------- -------------------------------------------------- ------------------- 10 job_test; trunc(sysdate+1)+3/24 2013-06-05 03:00:00 8 job_test; trunc(last_day(sysdate)+3)+3/24+30/1440 2013-07-03 03:30:00 9 job_test; trunc(next_day(sysdate,4))+3/24+30/1440 2013-06-05 03:30:00
一朋友還告訴我了一種拼接的方法,有興趣的可以看看
每月3號早上10:00
variable job1 number; begin dbms_job.submit(:job1,'job_test;',sysdate,'to_date(to_char(add_months(sysdate,1),''yyyymm'')||''03 10:00:00'',''yyyy-mm-dd hh24:mi:ss'')'); commit; end; /
其他的...
每小時
dbms_job.submit(:job1,'job_test;',sysdate,'sysdate+1/24');
每十分鍾
dbms_job.submit(:job1,'job_test;',sysdate,'sysdate+10/1440');
最后到指定某個特定時間點
variable job1 number; begin dbms_job.submit(:job1,'job_test;',to_date('2013-06-04 20:00:00','YYYY-MM-DD HH24:MI:SS'),''); commit; end; / SQL> select job,what,interval,to_char(next_date,'yyyy-mm-dd hh24:mi:ss') from user_jobs; JOB WHAT INTERVAL TO_CHAR(NEXT_DATE,' ---- -------------------------------------------------- -------------------------------------------------- ------------------- 12 job_test; null 2013-06-04 20:00:00
在這里繞了點彎路,腦袋一直往前面習慣性的intervel設置
其實只執行一次next_date就妥妥的 -_-
七、dbms_job的具體語法
先以dbms_job.change為例
DBMS_JOB.CHANGE( JOB IN BINARY_INTEGER, --job號 WHAT IN VARCHAR2, --執行什么 NEXT_DATE, --下一次執行時間 INTERVAL IN VARCHAR2, --執行間隔 INSTANCE IN BINARY_INTEGER DEFAULT NULL, FORCE IN BOOLEAN DEFAULT FALSE );
所以
exec dbms_job.change(4,null,null,'sysdate+1/1440'); __| |__ |___ |____________ | | | | job號 what next_date interval
commit;
DBMS_Job包含以下子過程:
1、Broken()過程:更新一個已提交的工作的狀態,可用於臨時停止任務
PROCEDURE BROKEN ( JOB IN BINARY_INTEGER, BROKENIN BOOLEAN, NEXT_DATE IN DATE := SYSDATE )
2、change()過程:用來改變指定工作的設置
DBMS_JOB.CHANGE( JOB IN BINARY_INTEGER, WHAT IN VARCHAR2, NEXT_DATE, INTERVAL IN VARCHAR2, INSTANCE IN BINARY_INTEGER DEFAULT NULL, FORCE IN BOOLEAN DEFAULT FALSE );
3、Interval()過程:用來顯式地設置重執行一個工作之間的時間間隔數。
PROCEDURE INTERVAL ( JOB IN BINARY_INTEGER, INTERVAL IN VARCHAR2 )
4、Isubmit()過程:用來用特定的工作號提交一個工作
PROCEDURE ISUBMIT ( JOB IN BINARY_INEGER, WHAT IN VARCHAR2, NEXT_DATE IN DATE, INTERVAL IN VARCHAR2, NO_PARSE IN BOOEAN := FALSE )
5、Next_Date()過程:用來顯式地設定一個工作的執行時間
PROCEDURE NEXT_DATE ( JOB IN BINARY_INEGER, NEXT_DATE IN DATE )
6、Remove()過程:來刪除一個已計划運行的工作
PROCEDURE REMOVE(JOB IN BINARY_INEGER);
7、Run()過程:用來立即執行一個指定的工作
PROCEDURE RUN(JOB IN BINARY_INEGER)
8、Submit()過程:工作被正常地計划好
PROCEDURE SUBMIT ( JOB OUT BINARY_INEGER, WHAT IN VARCHAR2, NEXT_DATE IN DATE, INTERVAL IN VARCHAR2, NO_PARSE IN BOOEAN := FALSE )
9、User_Export()過程:返回一個命令,此命令用來安排一個存在的工作以便此工作能重新提交。
PROCEDURE USER_EXPORT ( JOB IN BINARY_INEGER, MY_CALL IN OUT VARCHAR2 )
10、What()過程:可以用於更改要執行的任務
PROCEDURE WHAT ( JOB IN BINARY_INEGER, WHAT IN OUT VARCHAR2 )
整理完上面的后,想想,以上這些難道要死記?要背手冊?
其實...可以通過desc獲得:
很多的dbms工具包都可以通過desc查看
SQL> desc dbms_job; FUNCTION BACKGROUND_PROCESS RETURNS BOOLEAN PROCEDURE BROKEN Argument Name Type In/Out Default? ------------------------------ ----------------------- ------ -------- JOB BINARY_INTEGER IN BROKEN BOOLEAN IN NEXT_DATE DATE IN DEFAULT PROCEDURE CHANGE Argument Name Type In/Out Default? ------------------------------ ----------------------- ------ -------- JOB BINARY_INTEGER IN WHAT VARCHAR2 IN NEXT_DATE DATE IN INTERVAL VARCHAR2 IN INSTANCE BINARY_INTEGER IN DEFAULT FORCE BOOLEAN IN DEFAULT PROCEDURE INSTANCE Argument Name Type In/Out Default? ------------------------------ ----------------------- ------ -------- JOB BINARY_INTEGER IN INSTANCE BINARY_INTEGER IN FORCE BOOLEAN IN DEFAULT PROCEDURE INTERVAL Argument Name Type In/Out Default? ------------------------------ ----------------------- ------ -------- JOB BINARY_INTEGER IN INTERVAL VARCHAR2 IN PROCEDURE ISUBMIT Argument Name Type In/Out Default? ------------------------------ ----------------------- ------ -------- JOB BINARY_INTEGER IN WHAT VARCHAR2 IN NEXT_DATE DATE IN INTERVAL VARCHAR2 IN DEFAULT NO_PARSE BOOLEAN IN DEFAULT FUNCTION IS_JOBQ RETURNS BOOLEAN PROCEDURE NEXT_DATE Argument Name Type In/Out Default? ------------------------------ ----------------------- ------ -------- JOB BINARY_INTEGER IN NEXT_DATE DATE IN PROCEDURE REMOVE Argument Name Type In/Out Default? ------------------------------ ----------------------- ------ -------- JOB BINARY_INTEGER IN PROCEDURE RUN Argument Name Type In/Out Default? ------------------------------ ----------------------- ------ -------- JOB BINARY_INTEGER IN FORCE BOOLEAN IN DEFAULT PROCEDURE SUBMIT Argument Name Type In/Out Default? ------------------------------ ----------------------- ------ -------- JOB BINARY_INTEGER OUT WHAT VARCHAR2 IN NEXT_DATE DATE IN DEFAULT INTERVAL VARCHAR2 IN DEFAULT NO_PARSE BOOLEAN IN DEFAULT INSTANCE BINARY_INTEGER IN DEFAULT FORCE BOOLEAN IN DEFAULT PROCEDURE USER_EXPORT Argument Name Type In/Out Default? ------------------------------ ----------------------- ------ -------- JOB BINARY_INTEGER IN MYCALL VARCHAR2 IN/OUT PROCEDURE USER_EXPORT Argument Name Type In/Out Default? ------------------------------ ----------------------- ------ -------- JOB BINARY_INTEGER IN MYCALL VARCHAR2 IN/OUT MYINST VARCHAR2 IN/OUT PROCEDURE WHAT Argument Name Type In/Out Default? ------------------------------ ----------------------- ------ -------- JOB BINARY_INTEGER IN WHAT VARCHAR2 IN
暫時over,有了再補充
by cycsa
http://www.cnblogs.com/cycsa