標籤:
在11g中,Oracle提供了一個建立的Scheduler特性,協助將作業實現自動化。它還可以協助你控制資源的利用與並可以將資料庫中的作業按優先順序執行。傳統的dbms_jobs的一個限制是它只能調度基於PL/SQL的作業,不能用來調度作業系統的可執行檔或指令碼。
Scheduler包括如下許可權:scheduler_admin角色包含所有的scheduler系統許可權,授權如下:SQL> grant scheduler_admin to djp01 2 / Grant succeeded. SQL>manage scheduler系統許可權允許做以下工作:‘建立、刪除和更改作業類,視窗和視窗組。停止作業提前啟動和停止視窗(關於這些組件在下文中進行介紹)。授權如下:SQL> grant manage scheduler to djp01 2 / Grant succeeded. SQL>create job系統許可權允許做如下工作:建立作業(job)、進度表(schedule)、程式(program)、鏈(chain)和事件(event)。(關於這些組件在下文中會進行介紹),授權如下:SQL> grant create job to djp01 2 / Grant succeeded. SQL>如果要執行的程式在不同的模式下,那麼必要擁有執行相應模式下的程式的執行許可權,如下execute any procedure。 Scheduler包括如下基本組件:(1)作業(job)作業是一個計劃執行一次或多次的任務。例子如下:SQL> alter session set nls_date_format = ‘yyyy-mm-dd hh24:mi:ss‘ 2 / Session altered. SQL> alter session set nls_timestamp_tz_format = ‘yyyy-mm-dd hh24:mi:ss.ff‘ 2 / Session altered. SQL> alter session set nls_timestamp_format = ‘yyyy-mm-dd hh24:mi:ss.ff‘ 2 / Session altered. SQL>
說明:在使用發送器時,會涉及一些時間的相關資訊,我這裡進行一些時間格式的設定方便使用。
SQL> create table emp_bak 2 as 3 select * 4 from employees 5 where 1 = 0 6 / Table created. SQL> SQL> begin 2 dbms_scheduler.create_job( 3 job_name=>‘test_job‘, 4 job_type=>‘PLSQL_BLOCK‘, 5 job_action=>‘insert into emp_bak select * from employees where rownum <= 200;‘, 6 start_date=>‘2012-12-09 14:40:00‘, 7 repeat_interval=>‘FREQ=DAILY;INTERVAL=2‘, 8 end_date=>‘2012-12-09 20:00:00‘, 9 comments=>‘insert old employees into the emp_bak table‘, 10 auto_drop=>false, 11 enabled=>true); 12 end; 13 / PL/SQL procedure successfully completed. SQL>說明:job_name指定作業的名稱;job_type指定要建立的作業的類型,其值包括PLSQL_BLOCK(PL/SQL塊),STORED_PROCEDURE(預存程序),EXECUTABLE(可執行檔或Java程式)。job_action指定作業要執行過程,命令或指令碼。start_date與end_date指定作業的啟動與結束時間。comments用於給當前作業添加註釋。enabled指定建立作業時,是否啟動或禁用作業,預設值為false,表示禁用;值為true,表啟用。auto_drop指定該作業執行完成後,是否自動將其刪除,預設值為true,表示執行完成後自動刪除該作業。repeat_interval指定作業執行的頻率,FREQ=DAILY;INTERVAL=2表示每天運行一次該作業。該值是一個日曆運算式(calendaring expression)由三個部分組成,Frequency: 這是運算式必須包含的部分,用FREQ指定,可能取的值為YEARLY,MONTHLY,WEEKLY,DAILY,HOURLY,MINUTELY和SECONDLY。repeat interval:這個時間間隔由INTERVAL關鍵字標識,表示執行的頻率。specific:提供一個作業何時啟動並執行詳細資料,可能取值為:BYMONTH,BYWEEKNO,BYYEARDAY,BYMONTHDAY,BYDAY,BYHOUR,BYMINUTE和BYSECOND。例如:BYMONTHDAY表示每月的某一天,BYDAY表示每周的某一天。以下是典型的日曆運算式:FREQ=DAILY;INTERVAL=3;每三天執行一次。FREQ=HOURLY;INTERVAL=2;每隔一小時執行一次。FREQ=WEEKLY,BYDAY=SUN;每個星期日執行一次。FREQ=WEEKLY;INTERVAL=2,BYDAY=FRI;每隔一周的周五執行一次。FREQ=MONTHLY;BYMONTHDAY=1;每月最後一天執行一次。FREQ=MINUTELY;INTERVAL=30;每半個小時執行一次。下面我們看一下執行的情況:SQL> select count(*) 2 from emp_bak 3 / COUNT(*)---------- 200 SQL>上述發送器的作業成功運行,下面我們看一些該作業的資訊: SQL> select job_style,job_type,job_action,program_name,state 2 from dba_scheduler_jobs 3 where job_name = upper(‘test_job‘) 4 / JOB_STYLE JOB_TYPE---------------------- --------------------------------JOB_ACTION--------------------------------------------------------------------------------PROGRAM_NAME--------------------------------------------------------------------------------STATE------------------------------REGULAR PLSQL_BLOCKinsert into emp_bak select * from employees where rownum <= 200; COMPLETED SQL>狀態顯示,該作業執行完成,該作業的類型為REGULAR(規律性的)。 作業的其他一些管理:禁用一個作業:SQL> exec dbms_scheduler.disable(‘test_job‘); PL/SQL procedure successfully completed. SQL>啟用一個作業:SQL> exec dbms_scheduler.enable(‘test_job‘); PL/SQL procedure successfully completed. SQL>運行一個作業:SQL> truncate table emp_bak; Table truncated. SQL> exec dbms_scheduler.run_job(‘test_job‘); PL/SQL procedure successfully completed. SQL> select count(*) 2 from emp_bak 3 / COUNT(*)---------- 200 SQL>說明:該運行相當於是手工執行一次相應的程式。停止一個作業:SQL> exec dbms_scheduler.stop_job(‘test_job‘);如果一個作業不在運行狀態,它將會出現ORA-27366錯誤。刪除一個作業:SQL> exec dbms_scheduler.drop_job(‘test_job‘); PL/SQL procedure successfully completed. SQL>
(2)進度表(schedule)
進度表是資料庫執行一個作業的時間及頻率的說明。假如有一些作業都是在大致相同的時間內啟動並執行,那麼,可以使用一個進度表,可以化這些作業的建立與管理。例子如下:SQL> begin 2 dbms_scheduler.create_schedule( 3 schedule_name=>‘test_schedule‘, 4 start_date=>systimestamp, 5 repeat_interval=>‘FREQ=MINUTELY;INTERVAL=30‘, 6 end_date=>systimestamp+3, 7 comments=>‘Every 30 minute‘); 8 end; 9 / PL/SQL procedure successfully completed. SQL>下面我們查看該進度表的建立資訊:SQL> select start_date,end_date,schedule_type 2 from dba_scheduler_schedules 3 where schedule_name = upper(‘test_schedule‘) 4 / START_DATE---------------------------------------------------------------END_DATE---------------------------------------------------------------SCHEDULE_TYPE----------------2012-12-09 17:22:43.7810002012-12-12 17:22:43.000000CALENDAR SQL>
可以對已經建立的進度表進行相關屬性的更改,如下:
SQL> begin 2 dbms_scheduler.set_attribute( 3 name=>‘test_schedule‘, 4 attribute=>‘start_date‘, 5 value=>systimestamp); 6 end; 7 / PL/SQL procedure successfully completed. SQL>對已經有的進度表,我們可以進行刪除,如下:SQL> exec dbms_scheduler.drop_schedule(‘test_schedule‘); PL/SQL procedure successfully completed. SQL> (3)程式(program)程式包括關於一個scheduler作業的中繼資料。程式包括程式名,程式類型以及程式的動作。它是一個過程或是可執行指令碼的實際名稱。例子如下:SQL> begin 2 dbms_scheduler.create_program( 3 program_name=>‘test_program‘, 4 program_type=>‘STORED_PROCEDURE‘, 5 program_action=>‘auto_archive_emp‘, 6 enabled=>true, 7 comments=>‘use to execute the procedure of auto_archive_emp‘); 8 end; 9 / PL/SQL procedure successfully completed. SQL>說明:program_type與program_action同上述的job_type,job_action含義一樣,這裡不再說明。enabled表示該程式是否被啟用,預設值為false,表示禁用。我們可以用如下的方法對程式進行啟用或禁用:禁用一個程式:SQL> exec dbms_scheduler.disable(‘test_program‘); PL/SQL procedure successfully completed. SQL>啟用一個程式:SQL> exec dbms_scheduler.enable(‘test_program‘); PL/SQL procedure successfully completed. SQL>同樣,我們也可以進行刪除,如下:SQL> exec dbms_scheduler.drop_program(‘test_program‘); PL/SQL procedure successfully completed. SQL>對程式相關資訊的查看可以使用dba_scheduler_programs資料字典。
(4)鏈(chain)可以使用發送器鏈的概念將相關的程式連結在一起。因此,一個程式的成功運行,可能是以另外的程式成功運行為基礎;還可以是基於一個鍵而非程式啟動作業。鏈中連續的位置稱為鏈的“步驟(step)”,每個步驟指向另一個鏈,程式或事件。由於鏈使用Oracle Streams Rules Engine(Oracle流規則引擎對象)。因此使用者必須具有create job 和Rules Engine許可權才能建立一個鏈。例子如下:進行如下授權:SQL> begin 2 dbms_rule_adm.grant_system_privilege( 3 dbms_rule_adm.create_rule_obj,‘djp01‘); 4 dbms_rule_adm.grant_system_privilege( 5 dbms_rule_adm.create_rule_set_obj,‘djp01‘); 6 dbms_rule_adm.grant_system_privilege( 7 dbms_rule_adm.create_evaluation_context_obj,‘djp01‘); 8 end; 9 / PL/SQL procedure successfully completed. SQL>建立如下:SQL> begin 2 dbms_scheduler.create_chain( 3 chain_name=>‘test_chain‘, 4 comments=>‘A shain test‘); 5 end; 6 / PL/SQL procedure successfully completed. SQL>定義鏈步驟:SQL> begin 2 dbms_scheduler.define_chain_step( 3 chain_name=>‘test_chain‘, 4 step_name=>‘test_step1‘, 5 program_name=>‘test_program1‘); 6 dbms_scheduler.define_chain_step( 7 chain_name=>‘test_chain‘, 8 step_name=>‘test_step2‘, 9 program_name=>‘test_program2‘); 10 end; 11 / PL/SQL procedure successfully completed. SQL>說明:鏈步驟可以指向一個程式、鏈或事件。使用不同的參數進行標識。為了使用鏈有效運行,必須給鏈添加規則,用於確定步驟何時運行並指定運行條件。如下:SQL> begin 2 dbms_scheduler.define_chain_rule( 3 chain_name=>‘test_chain‘, 4 condition=>‘true‘, 5 action=>‘start test_step1‘); 6 dbms_scheduler.define_chain_rule( 7 chain_name=>‘test_chain‘, 8 condition=>‘test_step1 completed‘, 9 action=>‘start test_step2‘); 10 dbms_scheduler.define_chain_rule( 11 chain_name=>‘test_chain‘, 12 condition=>‘test_step2 completed‘, 13 action=>‘end‘); 14 end; 15 / PL/SQL procedure successfully completed. SQL>說明:在規則中,我們按照每一步的先後順序進行定義。如果每個步驟中都事務的先後關係,使用鏈是一個不錯的選擇。
在上述步驟完成之後,我們還需要對鏈進行啟用,如下:
SQL> exec dbms_scheduler.enable(‘test_chain‘); PL/SQL procedure successfully completed. SQL>這時,我們就可以在作業(job)中使用該鏈了(job_type指定為chain,job_action指定對應鏈的名稱,如test_chain)。我們還可以使用如下方式運行:SQL> begin 2 dbms_scheduler.run_chain( 3 chain_name=>‘test_chain‘, 4 start_steps=>‘test_step1,test_step2‘); 5 end; 6 / PL/SQL procedure successfully completed. SQL> (5)事件(event)
Scheduler使用Oracle Stream Advanced Qeueing(Oracle流進階隊列)觸發事件並啟動基於事件的資料庫作業。事件是一個應用程式或是進程注意到某個事件或動作時發出的一條訊息。有兩種類型的事件:Scheduler引發的事件和應用程式引發的事件。Scheduler引發的事件由Scheduler運行中的變化而導致,比如Scheduler作業成功完成是一個事件。應用程式引發的事件由Scheduler為啟動一個作業而使用或是消費。
使用基於事件的作業,只要在create_job過程上指定event_condition與queue_spec即可。但是事件的定義涉及到了,dbms_aqadm程式包的一些使用。我查看了dbms_aqadm包的聲明,沒有相關的注釋,之後試了幾次,沒有達到效果,這個問題有待解決。 下面我們來看幾個綜合使用的例子:SQL> begin 2 dbms_scheduler.create_job( 3 job_name=>‘test_job1‘, 4 program_name=>‘test_program1‘, 5 schedule_name=>‘test_schedule‘, 6 enabled=>true, 7 auto_drop=>false, 8 comments=>‘use program and schedule to create job‘); 9 end; 10 / PL/SQL procedure successfully completed. SQL>說明:在上述作業的建立中,我使用了程式與進度表。如果要進行調整,可以調整相應的程式與進行度即可。SQL> begin 2 dbms_scheduler.create_job( 3 job_name=>‘test_job2‘, 4 schedule_name=>‘test_schedule‘, 5 job_type=>‘chain‘, 6 job_action=>‘test_chain‘, 7 enabled=>true, 8 auto_drop=>false, 9 comments=>‘use chain to create job‘); 10 end; 11 / PL/SQL procedure successfully completed. SQL>說明:在建立job時,我們兩樣也可以指定一個鏈。如果要指定鏈,那麼job_type為chain,job_action為所建立的鏈名。
Oracle 發送器(scheduler)摘自一位大神