1. 程式人生 > >Oracle 使用DBMS_JOB和DBMS_SCHEDULER 建立定時任務 建立管理job示例

Oracle 使用DBMS_JOB和DBMS_SCHEDULER 建立定時任務 建立管理job示例

 

使用DBMS_JOB和DBMS_SCHEDULER建立、管理job示例

原創 Oracle 作者:Hoegh 時間:2015-04-28 16:52:41  6439  0

        DBMS_JOB和DBMS_SCHEDULER都是Oracle提供的程式包,都可以用來建立、管理job,其中DBMS_SCHEDULER的功能更為強大。先解釋scheduler的基礎概念,scheduler 包含了以下幾個實體物件: 

 

  1. Program -- 提供了scheduler 將要執行什麼,包含program name,program type(PL/SQ塊、儲存過程、外部程式),program action(具體的程式實體,比如說一個PL/SQL塊、或者是儲存過程的名稱、或者是外部程式的路徑加名稱) 。 
  2. Schedules -- 指定何時何種頻率來執行job,可以被不同的job重複的利用。比如說我有兩個job都要求在每天的凌晨4點執行,那麼兩個job可以同時指定相同的schedule。 
  3. Jobs -- 具體的作業的名稱,依賴於那個program、schedule。也可以不指定program、schedule,而直接寫入program、schedule的相應引數。

 

     另外,需要注意的是,通過DBMS_JOB和DBMS_SCHEDULER建立的job資訊儲存在不同的資料字典中,其中,通過DBMS_JOB建立的job資訊儲存在user_jobs,而通過

DBMS_SCHEDULER建立的job資訊儲存在user_scheduler_jobs中

下面,分別使用DBMS_JOB和DBMS_SCHEDULER來建立job。

使用DBMS_JOB
1.建立測試表
 

點選(此處)摺疊或開啟

  1. SQL> create table hoegh(h1 date); 
  2.  
  3. Table created
  4.  
  5. SQL>

2.建立儲存過程,向hoegh表中插入一條資料
 

點選(此處)摺疊或開啟

  1. SQL> 
  2. SQL> create or replace procedure pro_hoegh is
  3.   2 begin
  4.   3 insert into hoegh values(sysdate);
  5.   4 COMMIT;
  6.   5 end pro_hoegh;
  7.   6 /
  8.  
  9. Procedure created
  10.  
  11. SQL>

3.建立job
 

點選(此處)摺疊或開啟

  1. SQL> 
  2. SQL> variable job1 number
  3. SQL> begin
  4.   2 dbms_job.submit(:job1,\'pro_hoegh;\',sysdate,\'sysdate+1/1440\');--每天1440分鐘,即一分鐘執行test過程一次
  5.   3 end;
  6.   4 /
  7.  
  8. PL/SQL procedure successfully completed
  9. job1
  10. ---------
  11. 1
  12.  
  13. SQL>

4.執行job
 

點選(此處)摺疊或開啟

  1. SQL> 
  2. SQL> begin
  3.   2 dbms_job.run(:job1);
  4.   3 end;
  5.   4 /
  6.  
  7. PL/SQL procedure successfully completed
  8. job1
  9. ---------
  10. 1
  11.  
  12. SQL>

兩分鐘後,查詢測試表,確認job是否正常執行
 

點選(此處)摺疊或開啟

  1. SQL> select to_char(h1,\'yyyy-mm-dd HH24:mi:ss\') H1 from hoegh;
  2.  
  3. H1
  4. -------------------
  5. 2015-04-28 16:08:23
  6. 2015-04-28 16:07:21
  7.  
  8. SQL>


5.停止job
 

點選(此處)摺疊或開啟

  1. SQL> 
  2. SQL> begin
  3.   2 dbms_job.broken(1,true);
  4.   3 end;
  5.   4 /
  6.  
  7. PL/SQL procedure successfully completed
  8.  
  9. SQL>

其中,1是建立job是定義的變數值,可以唯一標識一個job
6.啟用job

 

點選(此處)摺疊或開啟

  1. SQL> 
  2. SQL> begin
  3.   2 dbms_job.broken(1,false);
  4.   3 end;
  5.   4 /
  6.  
  7. PL/SQL procedure successfully completed
  8.  
  9. SQL>

7.刪除job
 

點選(此處)摺疊或開啟

  1. SQL> 
  2. SQL> begin
  3.   2 dbms_job.remove(1);
  4.   3 end;
  5.   4 /
  6.  
  7. PL/SQL procedure successfully completed
  8.  
  9. SQL>


使用DBMS_SCHEDULER
1.建立測試表

 

點選(此處)摺疊或開啟

  1. SQL> create table hoegh(h1 date); 
  2.  
  3. Table created
  4.  
  5. SQL>

2.建立儲存過程,向hoegh表中插入一條資料
 

點選(此處)摺疊或開啟

  1. SQL> 
  2. SQL> create or replace procedure pro_hoegh is
  3.   2 begin
  4.   3 insert into hoegh values(sysdate);
  5.   4 COMMIT;
  6.   5 end pro_hoegh;
  7.   6 /
  8.  
  9. Procedure created
  10.  
  11. SQL>

3.建立schedule
schedule中定義了schedule名稱、起止時間、呼叫間隔等引數。

點選(此處)摺疊或開啟

  1. SQL> 
  2. SQL> begin
  3.   2 -- create_schedule
  4.   3 dbms_scheduler.create_schedule(schedule_name => \'schedule_hoegh\',
  5.   4 start_date => \'28-4月 -15 4.30.00.000 下午\',
  6.   5 repeat_interval => \'FREQ=MINUTELY; INTERVAL=1\',
  7.   6 end_date => \'29-4月 -15 4.30.00.000 下午\',
  8.   7 comments => \'TEST schedule\');
  9.   8 end;
  10.   9 /
  11.  
  12. PL/SQL procedure successfully completed
  13.  
  14. SQL>

4.建立program
在program中定義了程式的型別、具體操作、引數個數等引數

點選(此處)摺疊或開啟

  1. SQL> 
  2. SQL> begin
  3.   2 -- create_program
  4.   3 dbms_scheduler.create_program(program_name => \'program_hoegh\',
  5.   4 program_type => \'PLSQL_BLOCK\',
  6.   5 program_action => \'BEGIN PRO_HOEGH; END;\',
  7.   6 number_of_arguments => 0,
  8.   7 enabled => TRUE,
  9.   8 comments => \'TEST program\');
  10.   9 end;
  11.  10 /
  12.  
  13. PL/SQL procedure successfully completed
  14.  
  15. SQL>


5.建立job
在job中指定了job_name,以及相關聯的program_name、schedule_name等引數。

點選(此處)摺疊或開啟

  1. SQL> 
  2. SQL> begin
  3.   2 -- create_job
  4.   3 dbms_scheduler.create_job(job_name => \'job_hoegh\',
  5.   4 program_name => \'program_hoegh\',
  6.   5 schedule_name => \'schedule_hoegh\',
  7.   6 job_class => \'DEFAULT_JOB_CLASS\',
  8.   7 enabled => true,
  9.   8 auto_drop => true,
  10.   9 comments => \'TEST procedure\');
  11.  10 end;
  12.  11 /
  13.  
  14. PL/SQL procedure successfully completed
  15.  
  16. SQL>

6.執行job
 

點選(此處)摺疊或開啟

  1. SQL> 
  2. SQL> begin
  3.   2 -- Call the procedure
  4.   3 dbms_scheduler.run_job(job_name => \'job_hoegh\',
  5.   4 use_current_session => false);
  6.   5 end;
  7.   6 /
  8.  
  9. PL/SQL procedure successfully completed
  10.  
  11. SQL>

幾分鐘後,查詢測試表,確認job是否正常執行
 

點選(此處)摺疊或開啟

  1. SQL> select to_char(h1,\'yyyy-mm-dd HH24:mi:ss\') H1 from hoegh;
  2.  
  3. H1
  4. -------------------
  5. 2015-04-28 16:30:00
  6. 2015-04-28 16:31:00
  7. 2015-04-28 16:32:00
  8. 2015-04-28 16:24:25
  9.  
  10. SQL>

7.禁用job
 

點選(此處)摺疊或開啟

  1. SQL> 
  2. SQL> begin
  3.   2 dbms_scheduler.disable(\'job_hoegh\');
  4.   3 end;
  5.   4 /
  6.  
  7. PL/SQL procedure successfully completed
  8.  
  9. SQL> 
  10. SQL> select job_name,enabled,state from user_scheduler_jobs;
  11.  
  12. JOB_NAME ENABLED STATE
  13. ------------------------------ ------- ---------------
  14. JOB_HOEGH FALSE DISABLED
  15.  
  16. SQL>

8.啟用job
 

點選(此處)摺疊或開啟

  1. SQL> 
  2. SQL> begin
  3.   2 dbms_scheduler.enable(\'job_hoegh\');
  4.   3 end;
  5.   4 /
  6.  
  7. PL/SQL procedure successfully completed
  8.  
  9. SQL> 
  10. SQL> select job_name,enabled,state from user_scheduler_jobs;
  11.  
  12. JOB_NAME ENABLED STATE
  13. ------------------------------ ------- ---------------
  14. JOB_HOEGH TRUE SCHEDULED
  15.  
  16. SQL>

9.刪除job
 

點選(此處)摺疊或開啟

  1. SQL> 
  2. SQL> begin
  3.   2 dbms_scheduler.drop_job(\'job_hoegh\');
  4.   3 end;
  5.   4 /
  6.  
  7. PL/SQL procedure successfully completed
  8.  
  9. SQL> 
  10. SQL> select job_name,enabled,state from user_scheduler_jobs;
  11.  
  12. JOB_NAME ENABLED STATE
  13. ------------------------------ ------- ---------------
  14.  
  15. SQL>


 

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/30162081/viewspace-1609120/,如需轉載,請註明出處,否則將追究法律責任。

http://blog.itpub.net/30162081/viewspace-1609120/

 

 

 

 

 

Oracle 使用DBMS_SCHEDULER建立定時任務

2016年04月01日 17:08:06 Seabiscuit_92 閱讀數:6616 標籤: oracleDBMS_SCHEDULER 更多

個人分類: Oracle

在Oracle10g裡面,已經不贊成使用DBMS_JOB,推薦使用DBMS_SCHEDULER,它的健壯為排程提供更好的規劃和結構。下面我只簡單寫一個例子。 
begin 
    DBMS_SCHEDULER.CREATE_PROGRAM( 
    program_name => 'guozhw', 
    program_type => 'STORED_PROCEDURE', 
    program_action => 'guozhwTest', 
    number_of_arguments => 0, 
    enabled => true, 
    comments => '定時排程測試' 
    ); 
end; 
program_name:program的名字 
program_type:program的型別。STORED_PROCEDURE儲存過程 
program_action:要執行的程式。guozhwTest 儲存過程的名字 

  

  

舉例如下: 

BEGIN 
      DBMS_SCHEDULER.CREATE_PROGRAM ( 
         program_name            => 'PRM_CREATEDUNDATA', 
         program_action          => 'PKG_SCHEDULER.CREATEDUNDATA', 
         program_type            => 'STORED_PROCEDURE', 
         enabled                 => FALSE, 
     number_of_arguments     => 5, 
     comments            => '生成催繳資料'      
     ); 

  DBMS_SCHEDULER.DEFINE_PROGRAM_ARGUMENT(PROGRAM_NAME      => 'PRM_CREATEDUNDATA',
                                         ARGUMENT_POSITION => 1, 
                                         ARGUMENT_NAME     => 'I_BILLINGCYCLEID',
                                         ARGUMENT_TYPE     => 'VARCHAR2', 
                                         DEFAULT_VALUE     => NULL, 
                                         OUT_ARGUMENT      => FALSE); 
                                          
  DBMS_SCHEDULER.DEFINE_PROGRAM_ARGUMENT(PROGRAM_NAME      => 'PRM_CREATEDUNDATA',
                                         ARGUMENT_POSITION => 2, 
                                         ARGUMENT_NAME     => 'I_BUSINESSTYPE', 
                                         ARGUMENT_TYPE     => 'VARCHAR2', 
                                         DEFAULT_VALUE     => NULL, 
                                         OUT_ARGUMENT      => FALSE); 

  DBMS_SCHEDULER.DEFINE_PROGRAM_ARGUMENT(PROGRAM_NAME      => 'PRM_CREATEDUNDATA',
                                         ARGUMENT_POSITION => 3, 
                                         ARGUMENT_NAME     => 'I_STATE', 
                                         ARGUMENT_TYPE     => 'VARCHAR2', 
                                         DEFAULT_VALUE     => NULL, 
                                         OUT_ARGUMENT      => FALSE); 
                                          
  DBMS_SCHEDULER.DEFINE_PROGRAM_ARGUMENT(PROGRAM_NAME      => 'PRM_CREATEDUNDATA',
                                         ARGUMENT_POSITION => 4, 
                                         ARGUMENT_NAME     => 'I_BANKCODE', 
                                         ARGUMENT_TYPE     => 'VARCHAR2', 
                                         DEFAULT_VALUE     => NULL, 
                                         OUT_ARGUMENT      => FALSE); 

  DBMS_SCHEDULER.DEFINE_PROGRAM_ARGUMENT(PROGRAM_NAME      => 'PRM_CREATEDUNDATA',
                                         ARGUMENT_POSITION => 5, 
                                         ARGUMENT_NAME     => 'I_OPERATORCODE', 
                                         ARGUMENT_TYPE     => 'VARCHAR2', 
                                         DEFAULT_VALUE     => NULL, 
                                         OUT_ARGUMENT      => FALSE); 

  DBMS_SCHEDULER.ENABLE(NAME => 'PRM_CREATEDUNDATA'); 
  COMMIT; 
END; 

  

  

  

之後就可以在select * from sys.USER_SCHEDULER_PROGRAMS t中看到program了 

  

  

  

×××××××××××××××××××××××××××××××××××××××××***********************************************************

最近遇到一個CASE,要做定時任務,想來想去,還是先看看Oracle提供了啥.. 
Oracle10g引入了一種新的作業排程程式:dbms_scheduler,通過如下命令可以檢視它包含一些什麼功能, 
SQL> desc sys.dbms_scheduler; 
... 
不過,最好還是用PL/SQL dev或者TOAD來展開包頭,這樣所有功能和註釋都一幕瞭然了。 
在Oracle9i,我們都是job來執行定時任務,例如定時備份一些資料,定時清理一下歸檔。在Oracle10g裡面,已經不 
贊成試用DBMS_JOB,而是推薦使用DBMS_SCHEDULER,它更加的複雜和健壯,為排程提供更好的規劃和結構。 
dbms_scheduler把建立一個作業分成了不同的部分:dbms_scheduler,program和job,下面我們依次來建立一個例子。 
首先建立一個測試表: 
SQL> desc user118800; 
Name     Type     Nullable Default Comments 
------------- ------------ -------- ------- -------- 
SN       NUMBER           序列    
AREACODE   VARCHAR2(4)         區號    
DEVICESNUMBER VARCHAR2(12)         電話號碼 
READ     INTEGER       0   是否讀取 
BIT     INTEGER           業務位    
DDATE     DATE     Y            
有如下儲存過程: 
create or replace procedure pro_test is 
begin 
UPDATE user118800 SET READ=1,ddate=SYSDATE WHERE READ=0 AND ROWNUM <2; 
COMMIT; 
--sys.dbms_lock.sleep(120); 
end pro_test; 
這個測試,就是用過程來更新user118800表裡面的一行資料,並記錄下更新時間,接著我們就建立作業來定時執行。 
建立一個scheduler: 
/************************************************************* 
* Schedule Administration Procedures 
************************************************************* 
*/ 
-- Schedule attributes which can be used with set_attribute/get_attribute are : 
-- 
-- repeat_interval   - VARCHAR2 
--           an expression using the calendar syntax 
-- comments     - VARCHAR2 
--           an optional comment. 
-- end_date     - TIMESTAMP WITH TIME ZONE 
--           cutoff date after which the schedule will not specify 
--           any dates 
-- start_date   - TIMESTAMP WITH TIME ZONE 
--           start or reference date used by the calendar syntax 
-- 
-- Schedules cannot be enabled and disabled. 
-- Create a named schedule. This must be a valid schedule. 
PROCEDURE create_schedule( 
schedule_name     IN VARCHAR2, 
start_date       IN TIMESTAMP WITH TIME ZONE DEFAULT NULL, 
repeat_interval     IN VARCHAR2, 
end_date       IN TIMESTAMP WITH TIME ZONE DEFAULT NULL, 
comments       IN VARCHAR2         DEFAULT NULL); 
這是建立scheduler的儲存過程,執行如下: 
begin 
-- Call the procedure 
sys.dbms_scheduler.create_schedule(schedule_name => 'your schedule_name', 
                start_date => '27-8月 -07 12.00.00.000 上午', 
                repeat_interval => 'FREQ=MINUTELY; INTERVAL=1', 
                end_date => '28-8月 -07 12.00.00.000 上午', 
                comments => 'TEST SCHEDULER'); 
end; 
這裡需要注意的是,引數start_date和end_date都是TIMESTAMP 型別,在輸入的時候要遵循它們的格式, 
往往doc裡面的格式都是英文環境下的,這個時候你要通過查詢字典nls_database_parameters或者 
select to_timestamp(sysdate) from dual; 來獲得格式。 
repeat_interval是排程執行的時間間隔,本例是每分鐘執行一次 
repeat_interval => 'FREQ=HOURLY; INTERVAL=1' 
每小時執行一次 
repeat_interval => 'FREQ=DAILY INTERVAL=1' 
每天執行一次 
更詳細的說明,要查詢doc。另外它還有一個過程dbms_scheduler.evaluate_calendar_string是估算下一次執行的時間的。 
第二步,建立一個program 
/************************************************************* 
* Program Administration Procedures 
************************************************************* 
*/ 
-- Program attributes which can be used with set_attribute/get_attribute are: 
-- 
-- program_action   - VARCHAR2 
--           This is a string specifying the action. In case of: 
--           'PLSQL_BLOCK': PLSQL code 
--           'STORED_PROCEDURE: name of the database object 
--           representing the type (optionally with schema). 
--           'EXECUTABLE': Full pathname including the name of the 
--           executable, or shell script. 
-- program_type   - VARCHAR2 
--           type of program. This must be one of the supported 
--           program types. Currently these are 
--           'PLSQL_BLOCK', 'STORED_PROCEDURE', 'EXECUTABLE' 
-- comments       - VARCHAR2 
--           an optional comment. This can describe what the 
--           program does, or give usage details. 
-- number_of_arguments- PLS_INTEGER 
--           the number of arguments of the program that can be set 
--           by any job using it, these arguments MUST be defined 
--           before the program can be enabled 
-- enabled       - BOOLEAN 
--           whether the program is enabled or not. When the program 
--           is enabled, checks are made to ensure that the program 
--           is valid. 
-- Create a new program. The program name can be optionally qualified with a 
-- schema. If enabled is set to TRUE, validity checks will be performed and 
-- the program will be created in an enabled state if all are passed. 
PROCEDURE create_program( 
program_name       IN VARCHAR2, 
program_type       IN VARCHAR2, 
program_action     IN VARCHAR2, 
number_of_arguments   IN PLS_INTEGER DEFAULT 0, 
enabled       IN BOOLEAN DEFAULT FALSE, 
comments       IN VARCHAR2 DEFAULT NULL); 
執行如下: 
begin 
-- Call the procedure 
sys.dbms_scheduler.create_program(program_name => 'your program_name', 
                program_type => 'PLSQL_BLOCK', 
                program_action => 'BEGIN PRO_TEST; END;', 
                number_of_arguments => 0, 
                enabled => TRUE, 
                comments => 'comments'); 
end; 
這裡需要注意的是program_type,如果你要執行PLSQL塊,則選擇PLSQL_BLOCK,如果是sh指令碼,則'EXECUTABLE'。 
這裡我選擇PLSQL塊。 
第三步建立一個job 
-- create a job using a named schedule object and a named program object. 
-- If enabled is set TRUE, it will be attempted to enable this job after 
-- creating it. 
-- Values must be set for each argument of the program that does not have a 
-- default_value specified (before enabling the job). 
PROCEDURE create_job( 
job_name       IN VARCHAR2, 
program_name       IN VARCHAR2, 
schedule_name     IN VARCHAR2, 
job_class       IN VARCHAR2       DEFAULT 'DEFAULT_JOB_CLASS', 
enabled       IN BOOLEAN         DEFAULT FALSE, 
auto_drop       IN BOOLEAN         DEFAULT TRUE, 
comments       IN VARCHAR2       DEFAULT NULL); 
實際在10g提供的過程裡面,有6中create job的方法,而且也可以單獨建立作業,但這裡我們選擇其中一種。 
begin 
-- Call the procedure 
sys.dbms_scheduler.create_job(job_name => 'my test job', 
            program_name => 'your program_name', 
            schedule_name => 'your schedule_name', 
            job_class => 'DEFAULT_JOB_CLASS', 
            enabled => true, 
            auto_drop => true, 
            comments => 'comments'); 
end; 
這樣就完成了一個job的建立,下面就是執行它: 
begin 
-- Call the procedure 
sys.dbms_scheduler.run_job(job_name => 'my test job', 
            use_current_session => 'false'); 
end; 
use_current_session 這個引數要定義為false,它才能在後臺執行。 
建立以後的監控: 
檢視排程 
SELECT * FROM User_Scheduler_Schedules; 
檢視作業 
SELECT * FROM User_Scheduler_Jobs; 
檢視程式 
SELECT * FROM User_Scheduler_Programs; 
檢視執行中的作業,也就是PRO_TEST在執行階段的作業。前面的過程中,我定義了一個sys.dbms_lock.sleep(120); 
實際就是為了檢視這個檢視。 
SELECT * FROM User_Scheduler_Running_Jobs; 
檢視job的日誌 
SELECT * FROM User_Scheduler_Job_Log; 
如果日誌中有FAILeD的狀態,那麼就要檢視altersid.log了。 
好了,一個基本的排程例子就完成了。如果想更詳細的瞭解它,請閱讀該包頭的註釋,和查閱相關DOC 
Oracle&reg; Database 
PL/SQL Packages and Types Reference 
10g Release 2 (10.2) 
在9i的時候,job有一個煩人的問題,就是延時,一個job的執行耗時是10分鐘,inteval為1天,第一次執行為晚上12點, 
在以後的執行過程中,該job為逐漸按10分鐘遞增時間。10g的Scheduler解決了這個問題,但是我還是發現Scheduler同樣無法非同步的執行,我的inteval是1分鐘,但在程式中如果開啟
sleep(120)後,實際inteval就變成了120秒...它還是和job一樣,必須等待上一次任務的完成,這樣也沒有達到我的初衷。 
最後,我也應用中是否最終會使用Scheduler,還有待測試。除了Scheduler,在中間層,如EJB和Spring.... 

  

  

  

  

part 1 

1. 建立job 

job是什麼呢? 簡單的說就是計劃(schedule)加上任務說明. 另外還有一些必須的引數. 

這裡提到的"任務"可以是資料庫內部的儲存過程,匿名的PL/SQL塊,也可以是作業系統級別的指令碼. 

可以有兩種方式來定義"計劃": 
1) 使用DBMS_SCHDULER.CREATE_SCHEDULE 定義一個計劃; 
2) 呼叫DBMS_SCHDULER.CREATE_JOBE過程直接指定 (下面會詳細說明) 

在建立一個計劃時,你至少需要指定下面的屬性,它們是job執行所必須的: 

開始時間 (start_time); 

重複頻率 (repeat_interval); 

結束時間 (end_time) 


另外,對於一個job而言,還有很多的附加引數: 

job_class 
job_priority 
auto_drop 
restartable 
max_runs 
max_failures 
schedule_limit 
logging_level 


下面,我以問答的形式來具體解釋. 


Q1:怎麼從資料庫中查詢job的屬性 ? 

A1: 有兩種方法: 

1) 查詢(DBA|ALL|USER)_SCHEDULER_JOBS 檢視 
(提示: 根據使用者許可權的不同,選擇性的查詢 DBA|ALL|USER檢視) 

2) 呼叫DBMS_SCHEDULER包中的GET_ATTRIBUTE 過程 


Q2: 怎麼設定這些屬性呢? 

A2: 也是有兩種方法 

1) 在建立job時直接指定 

2) 呼叫DBMS_SCHEDULER包中的SET_ATTRIBUTE 過程 


Q3: "我需要什麼許可權才能建立job" ? 

A3: 你至少需要create_job這個系統許可權。如果使用者擁有create any job這個許可權, 
它可以建立屬主為任何使用者(SYS使用者除外)的job. 

預設情況下,job會被建立在當前的schema下,並且是沒有啟用的; 如果要使job一建立 
就自動啟用,需要顯式的設定enabled 屬性為true, 來看一個例子: 

begin 
dbms_scheduler.create_job 

job_name => 'ARC_MOVE', 
schedule_name => 'EVERY_60_MINS', 
job_type => 'EXECUTABLE', 
job_action => '/home/dbtools/move_arcs.sh', 
enabled => true, 
comments => 'Move Archived Logs to a Different Directory' 
); 
end; 



Q4: 能不能詳細地講述一下上面這個過程用到的各個引數? 

A4: 
job_name: 顧名思義,每個job都必須有一個的名稱 
schedule_name: 如果定義了計劃,在這裡指定計劃的名稱 
job_type: 目前支援三種類型: 

PL/SQL塊: PLSQL_BLOCK, 
儲存過程: STORED_PROCEDURE 
外部程式: EXECUTABLE (外部程式可以是一個shell指令碼,也可以是作業系統級別的指令). 

job_action: 根據job_type的不同,job_action有不同的含義. 
如果job_type指定的是儲存過程,就需要指定儲存過程的名字; 
如果job_type指定的是PL/SQL塊,就需要輸入完整的PL/SQL程式碼; 
如果job_type指定的外部程式,就需要輸入script的名稱或者作業系統的指令名 

enabled: 上面已經說過了,指定job建立完畢是否自動啟用 
comments: 對於job的簡單說明 



2. 指定job的執行頻率 

如果我們建立了一個job,並且希望它按照我們指定的日期和時間來執行,就需要定義 
job的重複頻度了. 例如每天執行,每週日的22:00執行, 每週一,三,五執行,每年的 
最後一個星期天執行等等. 
(說明:10G以前的版本,與作業系統的互動方面,實現的不是很好。例如要實現一個 
定期的rman備份任務,就需要結合OS的命令來實現,在UNIX下可以用crontab實現, 
在windows下用AT命令來實現) 

10G 在這方面有了很大的增強,因為建立job時可以直接指定作業系統的命令或者 
指令碼,再合理的定義job的執行頻率,可以很輕鬆地完成複雜的排程任務. 

10G 支援兩種模式的repeat_interval,一種是PL/SQL表示式,這也是dbms_job包 
中所使用的,例如SYSDATE+1, SYSDATE + 30/24*60; 另一種就是日曆表達式。 
例如MON表示星期一,SUN表示星期天,DAY表示每天,WEEK表示每週等等. 下面來 
看幾個使用日曆表達式的例子: 

repeat_interval => 'FREQ=HOURLY; INTERVAL=2' 
每隔2小時執行一次job 

repeat_interval => 'FREQ=DAILY' 
每天執行一次job 

repeat_interval => 'FREQ=WEEKLY; BYDAY=MON,WED,FRI" 
每週的1,3,5執行job 

repeat_interval => 'FREQ=YEARLY; BYMONTH=MAR,JUN,SEP,DEC; BYMONTHDAY=30' 
每年的3,6,9,12月的30號執行job 

用過crontab的人應該都有種似曾相識的感覺吧,呵呵 


下面再說說使用日曆表達式的規則: 

日曆表達式基本分為三部分: 第一部分是頻率,也就是"FREQ"這個關鍵字, 
它是必須指定的; 第二部分是時間間隔,也就是"INTERVAL"這個關鍵字, 
取值範圍是1-999. 它是可選的引數; 最後一部分是附加的引數,可用於 
精確地指定日期和時間,它也是可選的引數,例如下面這些值都是合法的: 
BYMONTH,BYWEEKNO,BYYEARDAY,BYMONTHDAY,BYDAY 
BYHOUR,BYMINUTE,BYSECOND 

詳細的引數說明請參考 dbms_scheduler的使用說明. 

既然說到了repeat_interval,你可能要問:"有沒有一種簡便的方法來得出, 
或者說是評估出job的每次執行時間,以及下一次的執行時間呢?" 

dbms_scheduler包提供了一個過程evaluate_calendar_string,可以很 
方便地完成這個需求. 來看下面的例子: 

SQL> set serveroutput on size 999999 

SQL> declare 
L_start_date TIMESTAMP; 
l_next_date TIMESTAMP; 
l_return_date TIMESTAMP; 

begin 
l_start_date := trunc(SYSTIMESTAMP); 
l_return_date := l_start_date; 
for ctr in 1..10 loop 
dbms_scheduler.evaluate_calendar_string( 
'FREQ=DAILY; BYDAY=MON,TUE,WED,THU,FRI; BYHOUR=7,15', 
l_start_date, l_return_date, l_next_date 
); 

dbms_output.put_line('Next Run on: ' || 
to_char(l_next_date,'mm/dd/yyyy hh24:mi:ss') 
); 

l_return_date := l_next_date; 

end loop; 
end; 



輸出結果如下: 

Next Run on: 03/22/2004 07:00:00 
Next Run on: 03/22/2004 15:00:00 
Next Run on: 03/23/2004 07:00:00 
Next Run on: 03/23/2004 15:00:00 
Next Run on: 03/24/2004 07:00:00 
Next Run on: 03/24/2004 15:00:00 
Next Run on: 03/25/2004 07:00:00 
Next Run on: 03/25/2004 15:00:00 
Next Run on: 03/26/2004 07:00:00 
Next Run on: 03/26/2004 15:00:00 

  

DBMS_SCHEDULER 中度解析: part 2 

3. 建立程式 (program) 

什麼是程式? 我的理解就是準備計劃需要的元資料(metadata),它 
包括以下部分: 

程式名; 

程式中用到的引數: 例如程式的型別,以及具體操作的描述 

來看一個例子 
begin 
dbms_scheduler.create_program( 
program_name=> 'DAILY_BACKUP_SH', 
program_type=> 'EXECUTABLE', 
program_action=> '/home/oracle/script/daily_backup.sh'); 
end; 


這個例子將會建立一個名為"DAILY_BACKUP_SH"的程式,型別是可執行的shell指令碼,指令碼的名稱是“/home/oracle/script/daily_backup.sh”


Q1: 程式和作業相比,有什麼區別呢? 

A1: 程式其實是可以與作業分離的,因此不同的使用者可以在不同的時間段去重用它.而一個作業是屬於特定的使用者的; 

另外,將程式與作業分離,也就激活了一個新的程式庫(Program Library),利用程式庫,使用者可以很自由地選擇特定的程式在特定的時間段執行,以及自由的配置程式執行時的引數.


Q2: 能否解釋一下 create_program與create_job的關係? 

A2: 首先,你應該知道建立程式並不是一個計劃的必須組成部分,一個計劃可以沒有程式,但是必須有一個已經定義好的作業; 
另外,program_action這個引數也是可選的,假如程式的型別是pl/sql 塊,你完全可以在建立作業時來指定它. 

上面已經提到了,程式和作業可以是分離的,這樣一個程式的具體執行(ACTION) 就可以靈活地確定。它既可以只執行一次,也可以在多個不同的作業中來重用這個執行. 這樣一來,在修改針對一個作業的計劃時就非常靈活,你不需要重新建立pl/sql塊.


Q3: 執行 create_program需要什麼許可權 ? 

A3: 要保證create_program能夠順利執行,你同樣需要CREATE JOB這個系統許可權. 如果一個使用者擁有了create any job這個許可權,它就可以建立屬主為任何使用者的程式(SYS使用者除外)

與建立作業一樣,一個程式建立完畢,預設的狀態也是非啟用的,當然你可以在建立程式時,顯式的設定enabled引數為true來 
啟用它. 


Q4: 能否介紹一下create_program這個過程的各個引數? 
更多的例子? 

A4: 
program_name: 指定程式的名稱; 

program_type: 目前只支援下面三種: 
STORED_PROCEDURE 
PLSQL_BLOCK 
EXECUTABLE 

program_action: (有長度限制,因為型別是varchar2) 

儲存過程的名稱; 
具體的pl/sql程式碼 
作業系統指令碼名稱 


來看一個使用pl/sql塊的例子 
BEGIN 
DBMS_SCHEDULER.CREATE_PROGRAM( 
program_name => 'LEO.UPDATE_STATS', 
program_type => 'PLSQL_BLOCK', 

program_action => 'DECLARE 
sUsername varchar2(30); 

cursor cur is select username from dba_users 
where username not in ('SYS','SYSTEM','SYSMAN','DBSNMP') 
and account_status='OPEN' and substr(username,1,5)<>'MGMT_' ; 

BEGIN 

OPEN cur; 
FETCH cur into sUsername; 

WHILE cur%Found 
LOOP 
DBMS_STATS.GATHER_SCHEMA_STATS (sUsername); 

FETCH cur into sUsername; 
END LOOP; 

close cur; 

END;'); 

END; 


上面這個例子建立一個名為"UPDATE_STATS"的程式,它的型別是PL/SQL 塊,完成更新非系統使用者的統計資訊的工作。在這個基礎上你可以定製一個合理的計劃,來定期執行這個程式.



4. 配置程式的引數 

先來看一個例子 

begin 
dbms_scheduler.create_program( 
program_name=> 'LEO.UPDATE_STATS_2', 
program_action=> 'LEO.UPDATE_SCHEMA_STATUS'); 
program_type=> 'STORED_PROCEDURE', 
number_of_arguments => 1, 
enabled => TRUE); 

dbms_scheduler.define_program_argument( 
program_name=> 'UPDATE_STATS_2', 
argument_name => 'SCHEMA_NAME', 
argument_position => 1, 
argument_type => 'varchar2', 
default_value => 'HR'); 
end; 


這個例程是不是很像上面的那個例子呢? 對,它們的區別只是 
在這個例子中,程式的型別是儲存過程,而不是pl/sql塊. 

解釋: 
使用define_program_argument這個過程來定義一個程式所需要的引數. 有兩點說明一下: 

1) 程式如果使用了引數,就必須事先指定,這樣才能在程式被job使用時生效; 

2) 定義程式的引數不會改變程式的啟用屬性。也就是說,如果一個程式是沒有啟用的狀態,運行了define_program_argument過程不會自動啟用這個程式.


關於許可權: 
預設情況下只有program的owner才能修改建立的程式,如果使用者被授予了alter 許可權 或者 create any job許可權,就可以修改屬主為另一個使用者的程式.



5. 建立計劃(Schedule) 

其實,如果你已經瞭解了怎樣建立作業和程式,就等於已經掌握怎樣建立計劃了。你需要做的附加工作只是指定計劃的開始時間,結束時間,重複頻率等等. 

來看一個例子 

begin 
dbms_scheduler.create_job( 
job_name=> 'leo.UPDATE_STATS_JOB', 
program_name=> 'leo.UPDATE_STATS_2', 
start_date=>'2005-06-20 11:00.00.000000 PM +8:00', 
repeat_interval=>'FREQ=MONTHLY;INTERVAL=1', 
end_date=>'2006-06-20 11:00.00.000000 PM +8:00', 
comments=>'Monthly statistics collection job'); 
end; 


start_date和end_date這兩個引數需要說明一下: 它們的資料型別 
是timestamp,因此需要精確的指定時間和時區. 時間格式繼承的是NLS_DATE_FORMAT這個初始化引數的值. 

下一部分介紹: 
1) 配置作業的引數; 
2) 建立/使用/管理作業,程式,計劃所需要的系統許可權. 



一些補充 

1.在10G R2 中, 如果用dbms_scheduler建立的job的型別為executable, 需要create external job 許可權。 

2. 在使用create_job或者create_schedule前,請先檢查 
NLS_DATE_LANGUAGE, NLS_DATE_FORMAT, 
NLS_TIMESTAMP_FORMAT, NLS_TIMESTAMP_TZ_FORMAT 
等引數的值, 通過alter session 命令來修改 

例如: 
SQL> select * from nls_session_parameters; 

alter session set NLS_DATE_LANGUAGE='AMERICAN'; 
alter session set NLS_DATE_FORMAT='dd-mm-yyyy hh24:mi:ss'; 
alter session set NLS_TIMESTAMP_TZ_FORMAT='dd-mm-yyyy HH:MI:SS.FF AM TZR' 

begin 
dbms_scheduler.create_job( 
job_name=> 'zip_emlog', 
job_type=> 'EXECUTABLE', 
job_action =>'/home/leo/zip_log.sh', 
enabled=>true, 
start_date=>'03-07-2005 9:30:00 PM + 8:00', 
repeat_interval=>'FREQ=MINUTELY;INTERVAL=30', 
end_date=>'31-07-2005 9:30:00 PM + 8:00', 
comments=>'Get a latest em log copy and compress it every 30 minutes'); 
end; 

 

 

 

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

 

dbms_scheduler介紹

10g引入的這個dbms_scheduler包,替代了之前的dbms_job包,該包功能更強大,可以將job需要的各種資源分開再進行組合。

1.program
1.1 create_program
引數說明:
  program_name——程式名稱
  program_type——程式型別(STORED_PROCEDURE,PLSQL_BLOCK,EXECUTABLE)
      STORED_PROCEDURE——ORACLE 中定義好的儲存過程
      PLSQL_BLOCK——是一段標準的pl/sql 程式碼
      EXECUTABLE——指定外部命令的命令列資訊(含路徑資訊)
  program_action——具體對應的執行內容,若為過程則為過程名
  enable——若為true則建立後啟用反之不啟用
  comments——註釋
例子:
BEGIN
   dbms_scheduler.create_program(program_name        => 'myprogram',
                                 program_type        => 'STORED_PROCEDURE',
                                 program_action      => 'p_test1',
                                 number_of_arguments => 1,
                                 enabled             => FALSE,
                                 comments            => '更新gi_pipe表');
   
END;
注:如果建立的程式需要輸入引數,則必須定義完引數後在啟用,即建立這個program時將enable設為false,否則提示:
    Ora-27456:程式“ ”的引數並未全部定義;然後再對該program定義引數即執行define_program_argument過程(見1.3)。

--檢視定義的program
SELECT * FROM user_scheduler_programs;

1.2 drop_program
引數說明:
program_name——要刪除的程式名稱
force——true或者false。如果為true則不管該program是否被job引用都會刪除,FALSE則若被引用無法刪除,預設為false。
例子:
BEGIN
   dbms_scheduler.drop_program(program_name => 'myprogram',force => TRUE);
END;

1.3 define_program_argument
引數說明:
program_name——程式名稱
argument_position——引數位置(也可以知道引數名稱選擇argument_name)
argument_type——引數型別
default_value——引數預設值

例子:
BEGIN
   dbms_scheduler.define_program_argument(program_name      => 'myprogram',
                                          argument_position => 1,
                                          argument_name     => 'p_lttid',
                           &nbs