詳細學習ORACLE JOBS


一點一點學習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




免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM