Oracle 10g Scheduler 特性
在10g 環(huán)境中,ORACLE 建議使用Scheduler 替換普通的job,來(lái)管理任務(wù)的執(zhí)行。其實(shí),將Scheduler 描述成管理job 的工具已經(jīng)太過片面了,10G版本中新增的Scheduler 絕不僅僅是創(chuàng)建任務(wù)這么簡(jiǎn)單.


一. 使用Jobs

所謂JOBS,其實(shí)就是Scheduler 管理的一個(gè)(或多個(gè))任務(wù)的執(zhí)行調(diào)度。


1.1 創(chuàng)建Jobs

通過DBMS_SCHEDULER 包來(lái)創(chuàng)建Jobs,是使用其CREATE_JOB 過程。在創(chuàng)建Job 時(shí),用戶可以指定要執(zhí)行的任務(wù),調(diào)度信息(啥時(shí)候執(zhí)行,執(zhí)行周期,終止日期等)以及其它一些任務(wù)相關(guān)的屬性。CREATE_JOB 過程調(diào)用還是比較簡(jiǎn)單的,例如:

create table TEST (id number);


CREATE OR REPLACE PROCEDURE IT

AS

BEGIN

insert into TEST VALUES(1);

END;


SQL> BEGIN

DBMS_SCHEDULER.CREATE_JOB (

job_name => 'JobTest',

job_type => 'STORED_PROCEDURE',

job_action => 'SYSTEM.IT',

start_date => sysdate,

repeat_interval => 'FREQ=MINUTELY;INTERVAL=10');

END;

/

PL/SQL 過程已成功完成。


事實(shí)上,有權(quán)限的話,用戶也可以創(chuàng)建其它SCHEMA 下的JOB,只需要在指定JOB_NAME 時(shí),按照schema.job_name 的格式即可。注意喲,這種情況下創(chuàng)建的JOB,其CREATED 與OWNER 有可能并不相同的喲。

當(dāng)使用CREATE_JOB 過程創(chuàng)建JOB 時(shí),可指定的參數(shù)值很多,只不過多數(shù)情況下用戶僅指定部分參數(shù)即可滿足需求。


其中,上例中指定的參數(shù),分別代表的含義如下:

JOB_NAME:指定任務(wù)的名稱,必選值,注意要確保指定的名稱唯一。

JOB_TYPE:任務(wù)執(zhí)行的操作類型,必選值,有下列幾個(gè)可選值:

   PLSQL_BLOCK:表示任務(wù)執(zhí)行的是一個(gè)PL/SQL 匿名塊。

   STORED_PROCEDURE:表示任務(wù)執(zhí)行的是ORACLE 過程(含PL/SQL PROCEDURE 和JAVA

PROCEDURE),本例中正是指定這一參數(shù)值。

   EXECUTABLE:表示任務(wù)執(zhí)行的是一個(gè)外部程序,比如說操作系統(tǒng)命令。

   CHAIN:表示任務(wù)執(zhí)行的是一個(gè)CHAIN。

JOB_ACTION:任務(wù)執(zhí)行的操作,必選值,應(yīng)與JOB_TYPE 類型中指定的參數(shù)相匹配。

比如說對(duì)于PL/SQL 匿名塊,此處就可以放置PL/SQL 塊的具體代表,類似DECLARE .. BEGIN ..END這類;如果是ORACLE 過程,那么此處應(yīng)該指定具體的過程名,注意由于任務(wù)執(zhí)行,即使過程中有OUT之類參數(shù),實(shí)際執(zhí)行時(shí)也不會(huì)有輸出的。

START_DATE:指定任務(wù)初次執(zhí)行的時(shí)間,本參數(shù)可為空,當(dāng)為空時(shí),表示任務(wù)立刻執(zhí)行,效果等同于指定該參數(shù)值為SYSDATE。

REPEAT_INTERVAL:指定任務(wù)執(zhí)行的頻率,比如多長(zhǎng)時(shí)間會(huì)被觸發(fā)再次執(zhí)行。本參數(shù)也可以為空,如果為空的話,就表示當(dāng)前設(shè)定的任務(wù)只執(zhí)行一次。REPEAT_INTERVAL 參數(shù)需要好好說說,因?yàn)檫@一參數(shù)與標(biāo)準(zhǔn)JOB 中的INTERVAL 參數(shù)有很大區(qū)別,相比之下,REPEAT_INTERVAL 參數(shù)的語(yǔ)法結(jié)構(gòu)要復(fù)雜的多。其中最重要的是FREQ 和INTERVAL 兩個(gè)關(guān)鍵字。

   FREQ 關(guān)鍵字用來(lái)指定間隔的時(shí)間周期,可選參數(shù)有:YEARLY, MONTHLY, WEEKLY, DAILY,HOURLY, MINUTELY, and SECONDLY,分別表示年、月、周、日、時(shí)、分、秒等單位。

   INTERVAL 關(guān)鍵字用來(lái)指定間隔的頻繁,可指定的值的范圍從1-99。

例如:REPEAT_INTERVAL=>'FREQ=DAILY;INTERVAL=1';表示每天執(zhí)行一次,如果將INTERVAL 改為7 就表示每7 天執(zhí)行一次,效果等同于FREQ=WEEKLY;INTERVAL=1。

一般來(lái)說,使用DBMS_SCHEDULER.CREATE_JOB 創(chuàng)建一個(gè)JOB,至少需要指定上述參數(shù)中的前3 項(xiàng)。除此之外,還可以在CREATE_JOB 時(shí),指定下列參數(shù):

   NUMBER_OF_ARGUMENTS:指定該JOB 執(zhí)行時(shí)需要附帶的參數(shù)的數(shù)量,默認(rèn)值為0,注意當(dāng)JOB_TYPE 列值為PLSQL_BLOCK 或CHAIN 時(shí),本參數(shù)必須設(shè)置為0,因?yàn)樯鲜鰞煞N情況下不支持附帶參數(shù)。

   END_DATE:指定任務(wù)的過期時(shí)間,默認(rèn)值為NULL。任務(wù)過期后,任務(wù)的STATE 將自動(dòng)被修改為COMPLETED,ENABLED 被置為FALSE。如果該參數(shù)設(shè)置為空的話,表示該任務(wù)永不過期,將一直按照

REPEAT_INTERVAL 參數(shù)設(shè)置的周期重復(fù)執(zhí)行,直到達(dá)到設(shè)置的MAX_RUNS 或MAX_FAILURES 值。

   JOB_CLASS:指定任務(wù)關(guān)聯(lián)的CLASS,默認(rèn)值為DEFAULT_JOB_CLASS。

   ENABLED:指定任務(wù)是否啟用,默認(rèn)值為FALSE。FALSE 狀態(tài)表示該任務(wù)并不會(huì)被執(zhí)行,除非被用戶手動(dòng)調(diào)用,或者用戶將該任務(wù)的狀態(tài)修改為TRUE。

   AUTO_DROP:當(dāng)該標(biāo)志被置為TRUE 時(shí),ORACLE 會(huì)在滿足條件時(shí)自動(dòng)刪除創(chuàng)建的任務(wù)

   任務(wù)已過期;

   任務(wù)最大運(yùn)行次數(shù)已達(dá)MAX_RUNS 的設(shè)置值;

   任務(wù)未指定REPEAT_INTERVAL 參數(shù),僅運(yùn)行一次;

該參數(shù)的默認(rèn)值即為TRUE。用戶在執(zhí)行CREATE_JOB 過程時(shí)可以手動(dòng)將該標(biāo)志指定為FALSE,當(dāng)參數(shù)值設(shè)置為FALSE 時(shí),即使?jié)M足上述提到的條件任務(wù)也不會(huì)被自動(dòng)刪除,這種情況下,唯一能夠?qū)е氯蝿?wù)被刪除的情況,就是用戶主動(dòng)調(diào)用DROP_JOB 過程。

   COMMENTS:設(shè)置任務(wù)的注釋信息,默認(rèn)值為NULL。


上面的例子創(chuàng)建了一個(gè)新的JOB,不過這個(gè)JOB 與普通JOB 不同喲,此時(shí)查詢USER_JOBS 視圖是查不到剛剛創(chuàng)建的JOB 的信息,因?yàn)檫@個(gè)JOB 是SCHEDULER 管理的JOB。要查詢SCHEDULER 管理的JOS,應(yīng)該通過USER_SCHEDULER_JOBS(當(dāng)然ALL_SCHEDULER_JOBS 和DBA_SCHEDULER_JOBS 也可以), 例如:


SQL> select job_name,job_type,job_action,to_char(start_date,'yyyy-mm-dd

hh24:mi:ss') TM,repeat_interval,enabled,state from user_scheduler_jobs;

JOB_NAME   JOB_TYPE         JOB_ACTION TM         REPEAT_INTERVAL           ENABL STATE

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

JOBTEST    STORED_PROCEDURE SYSTEM.IT  2009-09-25 FREQ=MINUTELY;INTERVAL=10  FALSE DISABLED


不過,細(xì)心的盆友可能會(huì)發(fā)現(xiàn),JOB 雖然成功創(chuàng)建了,但卻并未執(zhí)行.原因ENABLED 參數(shù)當(dāng)不顯式指定時(shí),該參數(shù)的默認(rèn)值為false,JOB自然不會(huì)運(yùn)行了。


1.2 管理Jobs

1.2.1 啟用Jobs

前面創(chuàng)建JOB 時(shí),由于未顯式的指定ENABLED 參數(shù),因此即使指定了START_DATE,不過默認(rèn)情況下JOB

不會(huì)自動(dòng)執(zhí)行。對(duì)于這種情況,DBMS_SCHEDULER 包中提供了一個(gè)過程ENABLE,可以用來(lái)修改JOB 的啟

用狀態(tài),調(diào)用方式非常簡(jiǎn)單,例如:

SQL> exec dbms_scheduler.enable('JOBTEST');

PL/SQL procedure successfully completed.


1.2.2 禁用Jobs

DBMS_SCHEDULER.ENABLE 僅用來(lái)將JOB(其實(shí)不僅僅對(duì)JOB 有效,對(duì)于CHAIN、PROGRAM 等也有效)的啟用狀態(tài)置為TRUE。如果想將其啟用狀態(tài)置為FALSE?簡(jiǎn)單,還有一個(gè)與該功能對(duì)應(yīng)的過程:

DBMS_SCHEDULER.DISABLE,例如:

JSSWEB> exec dbms_scheduler.disable('JOBTEST');

PL/SQL procedure successfully completed.

這兩個(gè)過程僅用來(lái)重置對(duì)象的狀態(tài),因此均可以無(wú)限次執(zhí)行,即使執(zhí)行時(shí)對(duì)象已經(jīng)被置為要指定的狀態(tài)。


1.2.3 修改Jobs

由于JOB 的屬性眾多,難免時(shí)不時(shí)的可能會(huì)遇到需要修改的情況,比如說前面創(chuàng)建JOB 時(shí)不小心,指定要

執(zhí)行的過程名輸入錯(cuò)誤(完全有可能,CREATE_JOB 在創(chuàng)建時(shí)不會(huì)自動(dòng)檢查指定的過程是否有效,從這方面考慮,

SCHEDULER 不如普通JOB 嚴(yán)謹(jǐn)哪),這種情況下就必然涉及到對(duì)JOB 的修改(或者說重定義),沒問題,

DBMS_SCHEDULER 包中專門提供了一個(gè)過程SET_ATTRIBUTE,可以用來(lái)修改任務(wù)的屬性值。

例如,修改剛剛創(chuàng)建的JOB:INSERT_TEST_TBL 執(zhí)行的過程,執(zhí)行語(yǔ)句如下:

JSSWEB> exec dbms_scheduler.set_attribute('JobTest','JOB_ACTION','SYSTEM.IT');

PL/SQL procedure successfully completed

當(dāng)然啦,我們這里執(zhí)行的這條語(yǔ)句,執(zhí)行跟沒執(zhí)行沒有區(qū)別,此處僅做示例,大家表深究。


SET_ATTRIBUTE 過程雖然僅有三個(gè)參數(shù),不過能夠修改的屬性值可是不少,以下列舉幾個(gè)較常用到的:

   LOGGING_LEVEL:指定對(duì)jobs 執(zhí)行情況記錄的日志信息級(jí)別。

SCHEDULER 管理的JOB 對(duì)任務(wù)的執(zhí)行情況專門進(jìn)行了記錄,同時(shí)用戶還可以選擇日志中記錄信息的級(jí)別,有下列三種選擇:

   DBMS_SCHEDULER.LOGGING_OFF:關(guān)閉日志記錄功能;

   DBMS_SCHEDULER.LOGGING_RUNS:對(duì)任務(wù)的運(yùn)行信息進(jìn)行記錄;

   DBMS_SCHEDULER.LOGGING_FULL:記錄任務(wù)所有相關(guān)信息,不僅有任務(wù)的運(yùn)行情況,甚至連任務(wù)的創(chuàng)建、修改等也均將記入日志。

提示: 查看SCHEDULER 管理的JOB , 可以通過USER_SCHEDULER_JOB_LOG 和USER_SCHEDULER_JOB_RUN_DETAILS 兩個(gè)視圖中查詢

   RESTARTABLE:指定jobs 運(yùn)行出錯(cuò)后,是否能夠適時(shí)重啟創(chuàng)建任務(wù)時(shí)如未明確指定,本參數(shù)默認(rèn)情況下設(shè)置為FALSE,如果設(shè)置為TRUE,就表示當(dāng)任務(wù)運(yùn)行時(shí)出錯(cuò),下次運(yùn)行時(shí)間點(diǎn)到達(dá)時(shí)仍會(huì)啟動(dòng),并且如果運(yùn)行仍然出錯(cuò),會(huì)繼續(xù)重新運(yùn)行,不過如果連接出錯(cuò)達(dá)到6 次,該job 就會(huì)停止。

   MAX_FAILURES:指定jobs 最大連續(xù)出錯(cuò)次數(shù)該參數(shù)值可指定的范圍從1-1000000,默認(rèn)情況下該參數(shù)設(shè)置為NULL,表示無(wú)限制。達(dá)到指定出錯(cuò)次數(shù)后,該job 會(huì)被自動(dòng)disable。

   MAX_RUNS:指定jobs 最大運(yùn)行次數(shù)

該參數(shù)值可指定的范圍從1-1000000,默認(rèn)情況下該參數(shù)設(shè)置為NULL,表示無(wú)限制(只是運(yùn)行次數(shù)無(wú)限制,實(shí)際job 會(huì)否繼續(xù)運(yùn)行,仍受制于end_date 以及max_failures 等參數(shù)的設(shè)置)。達(dá)到指定運(yùn)行次數(shù)后,該job 也將被自動(dòng)disable,并且狀態(tài)會(huì)被置為COMPLETED。

   JOB_TYPE:指定job 執(zhí)行的任務(wù)的類型

有四個(gè)可選值:'PLSQL_BLOCK', 'STORED_PROCEDURE', 'EXECUTABLE', and 'CHAIN'。

   JOB_ACTION:指定job 執(zhí)行的任務(wù).這一參數(shù)所指定的值依賴于JOB_TYPE 參數(shù)中的值, 比如說JOB_TYPE 設(shè)置為

'STORED_PROCEDURE',那么本參數(shù)值中指定的一定是ORACLE 中的過程名。

   START_DATE:指定job 初次啟動(dòng)的時(shí)間

   END_DATE:指定job 停止運(yùn)行的時(shí)間

本參數(shù)又與AUTO_DROP 相關(guān)聯(lián),如果AUTO_DROP 設(shè)置為TRUE 的話,那么一旦job 到達(dá)停止運(yùn)行的時(shí)間,該job 就會(huì)被自動(dòng)刪除,否則的話job 任何存在,不過狀態(tài)被修改為COMPLETED。

除此之外, 其它還包括MAX_RUN_DURATION , JOB_WEIGHT , INSTANCE_STICKINESS ,STOP_ON_WINDOW_CLOSE , JOB_PRIORITY , SCHEDULE_LIMIT , PROGRAM_NAME ,NUMBER_OF_ARGUMENTS , SCHEDULE_NAME , REPEAT_INTERVAL , JOB_CLASS , COMMENTS ,AUTO_DROP,EVENT_SPEC,RAISE_EVENTS 等等,這些參數(shù)所代表的意義此處不一一詳述,感興趣的朋友


僅從這些可設(shè)置屬性就可以看出,Scheduler 管理的job 確實(shí)非常靈活,上述提到了這些參數(shù),均可以使用

DBMS_SCHEDULER.SET_ATTRIBUTE 過程進(jìn)行設(shè)置。


另外需要注意一點(diǎn),除了用戶手動(dòng)創(chuàng)建的jobs 之外,數(shù)據(jù)庫(kù)在運(yùn)行過程中也有可能自動(dòng)創(chuàng)建jobs。對(duì)于這

類jobs 除非必要,否則不建議進(jìn)行修改。至于如何區(qū)分jobs 是用戶創(chuàng)建,還是數(shù)據(jù)庫(kù)自動(dòng)創(chuàng)建,可以通過

*_SCHEDULER_JOBS 視圖的SYSTEM 列來(lái)確定,如果該列顯示為TRUE,則表示由系統(tǒng)創(chuàng)建


1.2.4 執(zhí)行Jobs

雖然說jobs 大多都應(yīng)該是自動(dòng)執(zhí)行,不過經(jīng)過前面的示例,大家想必也認(rèn)識(shí)到了,并不是說創(chuàng)建了jobs 它

就會(huì)自動(dòng)執(zhí)行,是否能夠真正自動(dòng)執(zhí)行并不是由你的主觀意愿就能直接決定,而是由jobs 自身的多個(gè)相關(guān)屬性

決定。

關(guān)于jobs 自動(dòng)執(zhí)行的話題相信看完前面的內(nèi)容后,應(yīng)該都知道如何設(shè)置,下面主要演示,如何手動(dòng)調(diào)用jobs

并執(zhí)行,這其中,當(dāng)然少不了DBMS_SCHEDULER 包。例如,手動(dòng)執(zhí)行前面剛剛創(chuàng)建的job:JOBTEST:

JSSWEB> exec dbms_scheduler.run_job('JOBTEST');

PL/SQL procedure successfully completed

Jobs 每執(zhí)行一次,無(wú)論成功或失敗,均會(huì)在*_SCHEDULER_JOB_LOG 中生成一條對(duì)應(yīng)的記錄(前提是LOGGING_LEVEL 屬性值未設(shè)置為DBMS_SCHEDULER.LOGGING_OFF) , 同時(shí), 用戶也可以通過*_SCHEDULER_JOB_RUN_DETAILS 視圖查詢job 執(zhí)行的詳細(xì)信息。


1.2.5 停止Jobs

停止job 可以使用DMBS_SCHEDULER.STOP_JOB 過程,例如:

JSSWEB> exec dbms_scheduler.stop_job('JOBTEST');

PL/SQL procedure successfully completed


注意,STOP_JOB 過程不僅僅是更新job 的狀態(tài),而是停止當(dāng)前正在執(zhí)行的任務(wù),如果你處理的任務(wù)當(dāng)前未在運(yùn)行的話,那么執(zhí)行STOP_JOB 過程,會(huì)觸發(fā)ORA-27366 錯(cuò)誤。

停止Jobs 也會(huì)觸發(fā)一條任務(wù)的日志信息,對(duì)于執(zhí)行停止操作的job,其*_SCHEDULER_JOB_LOG 視圖的OPERATION 會(huì)記錄為'STOPPED',ADDITIONAL_INFO 列中記錄的信息類似'REASON="Stop job called by user:username"'。


1.2.6 刪除Jobs

刪除創(chuàng)建的job 就比較簡(jiǎn)單了,直接執(zhí)行DBMS_SCHEDULER.DROP_JOB 過程即可,例如:

JSSWEB> exec dbms_scheduler.drop_job('JOBTEST');

PL/SQL procedure successfully completed

刪除jobs 并不是修改該job 中某個(gè)字段的標(biāo)記值,而是直接刪除其在數(shù)據(jù)字典中的字義,因此被刪除的job

如果未來(lái)發(fā)現(xiàn)仍然需要,只能重建,而無(wú)法通過其它方式快速恢復(fù)。不過,刪除jobs 的操作,并不會(huì)級(jí)聯(lián)刪除

這些job 曾經(jīng)執(zhí)行過的日志信息。


二、使用Programs

進(jìn)入10g 版本之后,可以在ORACLE 中執(zhí)行操作系統(tǒng)命令,或是ORACLE 數(shù)據(jù)庫(kù)外的應(yīng)用,因?yàn)橛辛薉BMS_SCHEDULER,因?yàn)橛辛薖ROGRAM。


2.1 創(chuàng)建Programs

Scheduler 中的Program 對(duì)象并不是常規(guī)意義上的"程序"或"應(yīng)用",而就是一個(gè)"對(duì)象",由DBA 定義的,具

有執(zhí)行某項(xiàng)功能的特殊對(duì)象。Program 中實(shí)際執(zhí)行的操作可以分為下列三種類型:

   PL/SQL BLOCK:標(biāo)準(zhǔn)的pl/sql 代碼塊;

   STORED PROCEDURE:編譯好的PL/SQL 存儲(chǔ)過程,或者Java 存儲(chǔ)過程,以及外部的子程序;

   EXECUTEABLE:ORACLE 數(shù)據(jù)庫(kù)之外的應(yīng)用,比如操作系統(tǒng)命令等等。

創(chuàng)建Programs 使用DBMS_SCHEDULER.CREATE_PROGRAM 過程,該過程支持的參數(shù)如下:

SQL> desc dbms_scheduler.create_program;

Parameter Type Mode Default

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

PROGRAM_NAME VARCHAR2 IN

PROGRAM_TYPE VARCHAR2 IN

PROGRAM_ACTION VARCHAR2 IN

NUMBER_OF_ARGUMENTS BINARY_INTEGER IN Y

ENABLED BOOLEAN IN Y

COMMENTS VARCHAR2 IN Y

如上所示,前三項(xiàng)為必選參數(shù),各參數(shù)實(shí)際代表的意義如下:

   PROGRAM_NAME:指定一個(gè)program 名稱;

   PROGRAM_TYPE:Program 的類型,如前文中所述,Program 支持三種類型;

   PROGRAM_ACTION:實(shí)際執(zhí)行的操作,應(yīng)與前面PROGRAM_TYPE 參數(shù)關(guān)聯(lián)使用。比如說前面指定

了PROGRAM_TYPE 為"PLSQL_BLOCK",那么此處要執(zhí)行的action 就應(yīng)當(dāng)是一段標(biāo)準(zhǔn)的pl/sql 代碼。如果前

面指定PROGRAM_TYPE 為"STORED_PROCEDURE",那么此處要執(zhí)行的action 就應(yīng)當(dāng)是ORACLE 中定義好

的存儲(chǔ)過程(含Java 存儲(chǔ)過程),如果前面指定PROGRAM_TYPE 為"EXECUTABLE",那么此處就應(yīng)該指定外

部命令的命令行信息(含路徑信息);

   NUMBER_OF_ARGUMENTS:指定支持的參數(shù)個(gè)數(shù),默認(rèn)值為0 即沒有參數(shù)。每個(gè)program 最多能夠

支持255 個(gè)參數(shù),注意如果PROGRAM_TYPE 設(shè)置為PLSQL_BLOCK,那么本參數(shù)自動(dòng)忽略;

   ENABLED:指定是否將創(chuàng)建的program 置為有效狀態(tài),默認(rèn)情況下為false。

   COMMENTS:這個(gè)不用再說了吧,注釋信息。

下面實(shí)際操作一下看看,PL/SQL 或PROCEDURE 沒有挑戰(zhàn)(ORACLE 中直接即可調(diào)用),咱們創(chuàng)建一下

program,直接調(diào)用操作系統(tǒng)中的ls 命令,操作如下:

SQL> BEGIN

DBMS_SCHEDULER.CREATE_PROGRAM (

program_name => 'IPCONFIG',

program_action => 'C:\WINDOWS\system32\ipconfig.exe',

program_type => 'EXECUTABLE',

enabled => TRUE);

END;

/

PL/SQL procedure successfully completed.


2.2 管理Programs

CREATE_PROGRAM過程的參數(shù)時(shí)提到,每個(gè)program最多支持255 個(gè)參數(shù),要為program 添加參數(shù),可以通過DEFINE_PROGRAM_ARGUMENT 過程。不過在為其添加參數(shù)前,要注意program 的NUMBER_OF_ARGUMENTS 指定的數(shù)量,如果該值為0,那么為其添加參數(shù)時(shí)就會(huì)報(bào)錯(cuò)。

查詢創(chuàng)建的program 的信息,可以通過USER_SCHEDULER_PROGRAMS 視圖,例如:

SQL> select program_name,program_type,program_action,number_of_arguments,enabled

from user_scheduler_programs;


由于前面創(chuàng)建program 時(shí)並未指定NUMBER_OF_ARGUMENTS 的值,因此我們這里需要首先修改該值為

一個(gè)非0 值,操作如下:

SQL> exec dbms_scheduler.set_attribute('IPCONFIG','NUMBER_OF_ARGUMENTS',1);

PL/SQL procedure successfully completed.

沒錯(cuò), 操作還是使用DBMS_SCHEDULER.SET_ATTRIBUTE 過程。另外需要注意, program 的NUMBER_OF_ARGUMENTS 參數(shù)可是說想改就能改的,正常情況下該處理必須是在program 處于enabled 之前確認(rèn)完畢,否則會(huì)觸發(fā)ORA-27465 錯(cuò)誤,因此要修改program 的參數(shù)之前,必須首先確保要修改program 的enabled 狀態(tài)為false。


那么對(duì)于已經(jīng)處于enabled 狀態(tài)的program,如何修改其狀態(tài)屬性呢?其實(shí)很簡(jiǎn)單,前面操作jobs 時(shí)使用的

DBMS_SCHEDULER.DISABLE 過程還記的嗎?沒錯(cuò),該過程對(duì)于program 同樣好使,并且調(diào)用方式也完全一

樣,例如:

SQL> exec dbms_scheduler.disable('IPCONFIG');

PL/SQL procedure successfully completed.

另外,如果希望將program 置為enabled 狀態(tài),執(zhí)行DBMS_SCHEDULER.ENABLE 過程即可,這里不再例舉。

 

接下來(lái),就可以為剛剛創(chuàng)建的IPCONFIG添加路徑參數(shù),操作如下:

SQL> BEGIN

DBMS_SCHEDULER.DEFINE_PROGRAM_ARGUMENT (

program_name => 'IPCONFIG',

argument_position => 1,

argument_name => 'dirpath',

argument_type => 'VARCHAR2',

default_value => 'C:\');

END;

/

PL/SQL procedure successfully completed.


exec DBMS_SCHEDULER.ENABLE('IPCONFIG');


查詢?yōu)閜rogram 定義的參數(shù),可以通過USER_SCHEDULER_PROGRAM_ARGS 視圖,例如:

SQL> select program_name,argument_name,argument_position,argument_type

default_value from user_scheduler_program_args;


刪除program 的argument 操作也很簡(jiǎn)單,使用DROP_PROGRAM_ARGUMENT 過程即可,例如:

SQL> exec dbms_scheduler.drop_program_argument('IPCONFIG','dirpath');

PL/SQL procedure successfully completed.

該過程第一個(gè)參數(shù)指定program 名稱,第二個(gè)參數(shù)指定定義的argument 名稱,當(dāng)然此處也可以指定argument

的位置,即前例視圖返回結(jié)果中的ARGUMENT_POSITION 列值。

要?jiǎng)h除program 的話就更簡(jiǎn)單了,使用DROP_PROGRAM 過程即可,例如:

SQL> exec dbms_scheduler.drop_program('IPCONFIG');

PL/SQL procedure successfully completed.

當(dāng)然啦,刪除program 的同時(shí),也會(huì)刪除該program 對(duì)應(yīng)的所有arguments。


實(shí)際上SCHEDULER 中創(chuàng)建job 時(shí),也可以指定執(zhí)行外部的程序。SCHEDULER 中的Job 更像是之前版本

繼承過來(lái)的JOBS,只不過10g 中SCHEDULER 管理的JOBS 功能更加強(qiáng)大。Programs 與Jobs 不同的是,Jobs

是定義好的,定時(shí)執(zhí)行的任務(wù),而Programs 則是定義好的,等待被執(zhí)行的對(duì)象。


三、使用Schedules

10g 中新推出的SCHEDULER 可能確實(shí)會(huì)讓很多初接觸的朋友感覺暈頭暈?zāi)X,相比之前的jobs,

SCHEDULER 中新增的概念太多。比如說jobs,仍然可以理解成之前版本中的jobs,不過功能更加強(qiáng)大,比如說program,指的是運(yùn)行的程序(把要做什么單提出來(lái)了),比如說schedule,我將其翻譯為調(diào)度,定義執(zhí)行的

頻率或者說周期。


3.1 創(chuàng)建和管理Schedules

Schedule,中文直譯的話應(yīng)該理解成調(diào)度,從名字來(lái)看,它是一個(gè)邏輯實(shí)體,就是說當(dāng)創(chuàng)建了schedule 之后,數(shù)據(jù)庫(kù)中就肯定存在這一對(duì)象,只不過這一對(duì)象是用來(lái)描述job 的執(zhí)行周期。

創(chuàng)建schedule 可以通過DBMS_SCHEDULER.CREATE_SCHEDULE 過程,該過程支持的參數(shù)如下:

SQL>desc dbms_scheduler

SQL>desc dbms_scheduler.create_schedule;

Parameter Type Mode Default?

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

SCHEDULE_NAME VARCHAR2 IN

START_DATE TIMESTAMP WITH TIME ZONE IN Y

REPEAT_INTERVAL VARCHAR2 IN

END_DATE TIMESTAMP WITH TIME ZONE IN Y

COMMENTS VARCHAR2 IN Y

各參數(shù)分別代表含意如下:

   SCHEDULE_NAME:指定schedule 名稱,注意名稱不能重復(fù)。

   START_DATE:指定該調(diào)度的開始時(shí)間,可為空,當(dāng)為空時(shí)表示該調(diào)度暫不起用。

   REPEAT_INTERVAL:指定調(diào)度的執(zhí)行頻率或周期。

   END_DATE:指定調(diào)度的結(jié)束時(shí)間,可為空,為空時(shí)就表示該調(diào)度將一直進(jìn)行。

   COMMENTS:注釋信息。

這其中,比較有技術(shù)含量的是REPEAT_INTERVAL 參數(shù),對(duì)于這個(gè)參數(shù)大家應(yīng)該不會(huì)太陌生,因?yàn)榍懊娼?/p>

紹Jobs,也曾經(jīng)提到過同名的參數(shù),Schedules 中的REPEAT_INTERVAL 參數(shù)和Jobs 中的REPEAT_INTERVAL

參數(shù)功能完全相同,甚至參數(shù)格式也一模一樣。

REPEAT_INTERVAL 參數(shù)的語(yǔ)法結(jié)構(gòu)要復(fù)雜的多。其中最重要的是FREQ 和INTERVAL 兩個(gè)關(guān)鍵字。

   FREQ 關(guān)鍵字用來(lái)指定間隔的時(shí)間周期,可選參數(shù)有:YEARLY, MONTHLY, WEEKLY, DAILY,

HOURLY, MINUTELY, and SECONDLY,分別表示年、月、周、日、時(shí)、分、秒等單位。

   INTERVAL 關(guān)鍵字用來(lái)指定間隔的頻繁,可指定的值的范圍從1-99。

比如說, 當(dāng)指定REPEAT_INTERVAL=>'FREQ=DAILY;INTERVAL=1';就表示每天執(zhí)行一次, 如果將

INTERVAL 改為7 就表示每7 天執(zhí)行一次,效果等同于FREQ=WEEKLY;INTERVAL=1。


下面,創(chuàng)建一個(gè)schedule,指定調(diào)度為每周一次的頻率,執(zhí)行腳本如下:

SQL> BEGIN

DBMS_SCHEDULER.CREATE_SCHEDULE (

schedule_name => 'MySchedule',

start_date => SYSDATE,

repeat_interval => 'FREQ=WEEKLY; INTERVAL=1',

comments => 'Every 1 weeks');

END;

/

PL/SQL procedure successfully completed.


查詢當(dāng)前已經(jīng)創(chuàng)建的schedules,可以通過*_SCHEDULER_SCHEDULES 視圖(含DBA_,ALL_,USER_),例如,查看當(dāng)前用戶擁有的schedules,執(zhí)行語(yǔ)句如下:

SQL> select schedule_name,repeat_interval from user_scheduler_schedules;


如果要修改schedule 屬性的話,也是使用DBMS_SCHEDULER.SET_ATTRIBUTE 過程,該過程的調(diào)用方式前面已經(jīng)多次演示過,這里就不再重復(fù)舉例了,僅說明一點(diǎn),對(duì)于schedule 來(lái)說,能夠修改的屬性包括:

REPEAT_INTERVAL、COMMENTS、END_DATE、START_DATE 以及EVENT_SPEC。


至于刪除schedule,再簡(jiǎn)單不過,執(zhí)行DBMS_SCHEDULER.DROP_SCHEDULE 過程即可,例如:

SQL> EXEC DBMS_SCHEDULER.DROP_SCHEDULE('MY_FIRST_SCHEDULE');

PL/SQL procedure successfully completed.


3.2 Schedules調(diào)度Programs執(zhí)行的Jobs

通過schedule 調(diào)度program 的執(zhí)行的job。10g 版本中SCHEDULER 將JOB分成了多個(gè)部分,program 負(fù)責(zé)做什么,schedule 負(fù)責(zé)啥時(shí)候做,job 就簡(jiǎn)單了,一個(gè)字:做。

前面幾個(gè)小節(jié),已經(jīng)分別演示了創(chuàng)建管理Jobs,創(chuàng)建管理Programs 以及創(chuàng)建和管理Schedules,下面我

們通過實(shí)例來(lái)演示,如何創(chuàng)建通過schedule 調(diào)度program 的執(zhí)行的job 吧。


1. 我們用前面創(chuàng)建的Program: IPCONFIG,執(zhí)行操作系統(tǒng)命令ipconfig。

2. 用我們剛創(chuàng)建的schedule:MySchedule

3. 創(chuàng)建job,按照指定的schedule,執(zhí)行program,操作如下:

SQL> BEGIN

DBMS_SCHEDULER.CREATE_JOB (

job_name => 'ExecCmd',

program_name => 'IPCONFIG',

schedule_name => 'MySchedule',

enabled => true);

END;

/

PL/SQL procedure successfully completed.

創(chuàng)建job 時(shí),start_date,repeat_interval,job_action 等均無(wú)須指定,因?yàn)檫@些參數(shù)將由program 和schedule 來(lái)控

制。


這樣,操作完成后,ORACLE 就會(huì)自動(dòng)定時(shí)(當(dāng)前設(shè)置為每周執(zhí)行一次)program 中定義的操作。

要查看當(dāng)前的執(zhí)行情況,通過*_scheduler_job_run_details 即可查詢(*_scheduler_job_log 也可以,不過該視

圖中信息不如detail 中全面)。例如,查看剛剛創(chuàng)建的"ExecCmd"任務(wù)的執(zhí)行情況,執(zhí)行命令如下:

SQL> select log_id,log_date,status,additional_info from user_scheduler_job_run_details where job_name = 'ExecCmd';


3.3 設(shè)置Repeat Interval

Job 和Schedule 中REPEAT_INTERVAL 參數(shù)都是用來(lái)控制執(zhí)行的頻率或周期,雖然說周期是一個(gè)時(shí)間性概念,不過REPEAT_INTERVAL 指定的時(shí)候并不是一個(gè)時(shí)間值,而是由一組關(guān)鍵字描述的時(shí)間。

除了前面介紹Job 和Schedule 的REPEAT_INTERVAL 參數(shù)時(shí),提到該參數(shù)擁有FREQ 以及INTERVAL 兩個(gè)關(guān)鍵字,其實(shí)除此之外,還有如BYMONTH、BYWEEKNO、BYYEARDAY、BYDATE 等等參數(shù),可以用來(lái)進(jìn)行更精確的定義,比如通過BYMONTH 關(guān)鍵字指定調(diào)度運(yùn)行的月份,BYDAY 指定調(diào)度在哪天運(yùn)行等等。


REPEAT_INTERVAL 參數(shù)的詳細(xì)語(yǔ)法如下:

repeat_interval = regular_schedule | combined_schedule

==============================

regular_schedule = frequency_clause

[";" interval_clause] [";" bymonth_clause] [";" byweekno_clause]

[";" byyearday_clause] [";" bydate_clause] [";" bymonthday_clause]

[";" byday_clause] [";" byhour_clause] [";" byminute_clause]

[";" bysecond_clause] [";" bysetpos_clause] [";" include_clause]

[";" exclude_clause] [";" intersect_clause][";" periods_clause]

[";" byperiod_clause]

==============================

combined_schedule = schedule_list [";" include_clause]

[";" exclude_clause] [";" intersect_clause]

frequency_clause = "FREQ" "=" ( predefined_frequency | user_defined_frequency )

predefined_frequency = "YEARLY" | "MONTHLY" | "WEEKLY" | "DAILY" |

"HOURLY" | "MINUTELY" | "SECONDLY"

user_defined_frequency = named_schedule

==============================

interval_clause = "INTERVAL" "=" intervalnum

intervalnum = 1 through 99

bymonth_clause = "BYMONTH" "=" monthlist

monthlist = monthday ( "," monthday)*

month = numeric_month | char_month

numeric_month = 1 | 2 | 3 ... 12

char_month = "JAN" | "FEB" | "MAR" | "APR" | "MAY" | "JUN" |

"JUL" | "AUG" | "SEP" | "OCT" | "NOV" | "DEC"

byweekno_clause = "BYWEEKNO" "=" weeknumber_list

weeknumber_list = weeknumber ( "," weeknumber)*

weeknumber = [minus] weekno

weekno = 1 through 53

byyearday_clause = "BYYEARDAY" "=" yearday_list

yearday_list = yearday ( "," yearday)*

yearday = [minus] yeardaynum

yeardaynum = 1 through 366

bydate_clause = "BYDATE" "=" date_list

date_list = date ( "," date)*

date = [YYYY]MMDD [ offset | span ]

bymonthday_clause = "BYMONTHDAY" "=" monthday_list

monthday_list = monthday ( "," monthday)*

monthday = [minus] monthdaynum

monthdaynum = 1 through 31

byday_clause = "BYDAY" "=" byday_list

byday_list = byday ( "," byday)*

byday = [weekdaynum] day

weekdaynum = [minus] daynum

daynum = 1 through 53 /* if frequency is yearly */

daynum = 1 through 5 /* if frequency is monthly */

day = "MON" | "TUE" | "WED" | "THU" | "FRI" | "SAT" | "SUN"

byhour_clause = "BYHOUR" "=" hour_list

hour_list = hour ( "," hour)*

hour = 0 through 23

byminute_clause = "BYMINUTE" "=" minute_list

minute_list = minute ( "," minute)*

minute = 0 through 59

bysecond_clause = "BYSECOND" "=" second_list

second_list = second ( "," second)*

second = 0 through 59

bysetpos_clause = "BYSETPOS" "=" setpos_list

setpos_list = setpos ("," setpos)*

setpos = [minus] setpos_num

setpos_num = 1 through 9999

==============================

include_clause = "INCLUDE" "=" schedule_list

exclude_clause = "EXCLUDE" "=" schedule_list

intersect_clause = "INTERSECT" "=" schedule_list

schedule_list = schedule_clause ("," schedule_clause)*

schedule_clause = named_schedule [ offset ]

named_schedule = [schema "."] schedule

periods_clause = "PERIODS" "=" periodnum

byperiod_clause = "BYPERIOD" "=" period_list

period_list = periodnum ("," periodnum)*

periodnum = 1 through 100

==============================

offset = ("+" | "-") ["OFFSET:"] duration_val

span = ("+" | "-" | "^") "SPAN:" duration_val

duration_val = dur-weeks | dur_days

dur_weeks = numofweeks "W"

dur_days = numofdays "D"

numofweeks = 1 through 53

numofdays = 1 through 376

minus = "-"

這個(gè)語(yǔ)法形式看起來(lái)復(fù)雜無(wú)比,其實(shí)實(shí)用起來(lái)很簡(jiǎn)單,之所以看起來(lái)復(fù)雜,是因?yàn)槠涔δ芴^靈活。


例如:設(shè)置任務(wù)僅在周5 的時(shí)候運(yùn)行:

REPEAT_INTERVAL => 'FREQ=DAILY; BYDAY=FRI';

REPEAT_INTERVAL => 'FREQ=WEEKLY; BYDAY=FRI';

REPEAT_INTERVAL => 'FREQ=YEARLY; BYDAY=FRI';

上述三條語(yǔ)句雖然指定的關(guān)鍵字小有差異,不過功能相同。

設(shè)置任務(wù)隔一周運(yùn)行一次,并且僅在周5 運(yùn)行:

REPEAT_INTERVAL => 'FREQ=WEEKLY; INTERVAL=2; BYDAY=FRI';

設(shè)置任務(wù)在當(dāng)月最后一天運(yùn)行:

REPEAT_INTERVAL => 'FREQ=MONTHLY; BYMONTHDAY=-1';

設(shè)置任務(wù)在3 月10 日運(yùn)行:

REPEAT_INTERVAL => 'FREQ=YEARLY; BYMONTH=MAR; BYMONTHDAY=10';

REPEAT_INTERVAL => 'FREQ=YEARLY; BYDATE=0310';

上述兩條語(yǔ)句功能相同。

設(shè)置任務(wù)每10 隔天運(yùn)行:

REPEAT_INTERVAL => 'FREQ=DAILY; INTERVAL=10';

設(shè)置任務(wù)在每天的下午4、5、6 點(diǎn)時(shí)運(yùn)行:

REPEAT_INTERVAL => 'FREQ=DAILY; BYHOUR=16,17,18';

設(shè)置任務(wù)在每月29 日運(yùn)行:

REPEAT_INTERVAL => 'FREQ=MONTHLY; BYMONTHDAY=29';

設(shè)置任務(wù)在每年的最后一個(gè)周5 運(yùn)行:

REPEAT_INTERVAL => 'FREQ=YEARLY; BYDAY=-1FRI';

設(shè)置任務(wù)每隔50 個(gè)小時(shí)運(yùn)行:

REPEAT_INTERVAL => 'FREQ=HOURLY; INTERVAL=50';

另外,你是否在懷念常規(guī)job 中設(shè)置interval 的簡(jiǎn)便,雖然功能較弱,但是設(shè)置操作非常簡(jiǎn)單,無(wú)須懊惱,

其實(shí)SCHEDULER 中的REPEAT_INTERVAL 也完全可以按照那種方式設(shè)置,前面都說了,REPEAT_INTERVAL

實(shí)際上是指定周期,直接指定一個(gè)時(shí)間值,當(dāng)然也是周期嘍。

比如說,設(shè)置任務(wù)每天執(zhí)行一次,也可以設(shè)置REPEAT_INTERVAL 參數(shù)值如下:

REPEAT_INTERVAL => 'trunc(sysdate)+1'

又比如設(shè)置任務(wù)每周執(zhí)行一次:

REPEAT_INTERVAL => 'trunc(sysdate)+7'、


不過需要注意,這種方式僅用于創(chuàng)建SCHEDULER 中jobs 時(shí)使用,不能用于schedule。


四、使用Events

Event 直譯對(duì)應(yīng)的中文解釋是指事件,不過單純講事件畢竟太抽象了,舉個(gè)示例來(lái)形容吧。A(對(duì)應(yīng)某個(gè)應(yīng)用

程序,或者是ORACLE 中的進(jìn)程)在干活時(shí)突然眉頭一皺說道,不好,前方有情況,這可怎么辦!這時(shí),只見

它認(rèn)真想了想,過了一會(huì)兒臉上一喜說道:有了,俗話說早請(qǐng)示啊晚匯報(bào),出現(xiàn)情況要找領(lǐng)導(dǎo),趕緊給領(lǐng)導(dǎo)發(fā)

消息唄!于是B(也是對(duì)應(yīng)某個(gè)應(yīng)用或ORACLE 進(jìn)程)就收到了一條A 發(fā)過來(lái)的"前方有XX 情況"的消息,這個(gè)

過程就叫EVENT(含A 發(fā)消息以及B 接收消息)。

SCHEDULER 中有兩種觸發(fā)EVENT 的情況:

   Scheduler 觸發(fā)的Events

Scheduler 中觸發(fā)的Events,一般是說當(dāng)前schduler 中job 的狀態(tài)發(fā)生修改,類似job 啟動(dòng),或者運(yùn)行結(jié)束,或者達(dá)到運(yùn)行時(shí)間等諸如此類的動(dòng)作,都能夠拋出一個(gè)EVENT,接收到EVENT 的applicate 就可以根據(jù)這些信息進(jìn)行適當(dāng)?shù)奶幚怼?/p>

比如說,由于系統(tǒng)太過于繁忙,超出job 啟動(dòng)時(shí)間后30 分鐘,job 仍然沒能順利啟動(dòng),那么這個(gè)時(shí)候,Scheduler 就可以拋出一條EVENT 給外部的應(yīng)用,以便外部應(yīng)用能夠及時(shí)通知DBA,進(jìn)行處理。

   application 觸發(fā)的Events

外部的應(yīng)用也可以觸發(fā)Events,并且由Scheduler 來(lái)接收并處理這一類型的Events。所謂Scheduler 處理EVENT 就是指Scheduler 啟動(dòng)相應(yīng)的job 來(lái)執(zhí)行相關(guān)操作,這類job 在創(chuàng)建時(shí)專門聲明了event 的處理,這樣當(dāng)接收到EVENT 時(shí),這類job 就會(huì)啟動(dòng)。

Scheduler 使用Oracle 高級(jí)隊(duì)列來(lái)拋出以及銷毀Events。當(dāng)拋出Schduler 觸發(fā)的Events 時(shí),Scheduler 將消息入隊(duì)到默認(rèn)的event 隊(duì)列,application 則通過檢查該隊(duì)列來(lái)處理Events。當(dāng)拋出application 觸發(fā)的Events 時(shí),application 將消息入隊(duì)到處理job 對(duì)應(yīng)的隊(duì)列中。


下面我們也按照這兩個(gè)類型來(lái)介紹Scheduler 中的Events。


4.1 Scheduler拋出的Events

前面說了,Scheduler 拋出的Events 一般是指job 狀態(tài)改變時(shí)觸發(fā)的,那么是不是說只要job 狀態(tài)發(fā)生了改變,就會(huì)觸發(fā)Events,其實(shí)并非如此,因?yàn)槟J(rèn)情況下,job 是不觸發(fā)Events 的。

Scheduler 中的job 有一個(gè)屬性叫raise_events,專門用來(lái)設(shè)置job 觸發(fā)Events 的條件,該屬性在CREATE_JOB時(shí)不能執(zhí)行,因此默認(rèn)情況下該屬性不會(huì)賦值,自然也就不會(huì)觸發(fā)EVENT。要設(shè)置raise_events 屬性,只能是在job 創(chuàng)建完成后,通過SET_ATTRIBUTE 過程修改job 的raise_events 屬性。

例如,修改前面創(chuàng)建的job-,啟用raise_events 屬性,執(zhí)行語(yǔ)句如下:

SQL> BEGIN

DBMS_SCHEDULER.SET_ATTRIBUTE('JOBTEST', 'raise_events',DBMS_SCHEDULER.JOB_ALL_EVENTS);

END;

/

PL/SQL procedure successfully completed.


上述示例中指定的raise_events 屬性的屬性值DBMS_SCHEDULER.JOB_ALL_EVENTS,就是拋出Events的觸發(fā)條件。

觸發(fā)Events 的有下列的類型,分別代表不同的操作:

   job_started:JOB 啟動(dòng);

   job_succeeded:JOB 成功結(jié)束;

   job_failed:JOB 執(zhí)行失敗;

   job_broken:JOB 被置為BROKEN 狀態(tài);

   job_completed:JOB 達(dá)到最大運(yùn)行次數(shù),或者運(yùn)行的結(jié)束日期;

   job_stopped:JOB 被STOP_JOB 過程置為停止執(zhí)行的狀態(tài);

   job_sch_lim_reached:Job 的schedule 達(dá)到限定值;

   job_disabled:JOB 被置于DISABLE 狀態(tài);

   job_chain_stalled:運(yùn)行于chain 的JOB 被置于CHAIN_STALLED 狀態(tài);

   job_all_events:含上述提到的所有類型;

   job_run_completed:由于Job 運(yùn)行出錯(cuò)、成功結(jié)束或被手動(dòng)停止。


起用raise_events 后,Scheduler 就會(huì)按照設(shè)定的觸發(fā)條件,當(dāng)達(dá)到觸發(fā)條件時(shí),即會(huì)拋出事件信息到SYS.SCHEDULER$_EVENT_QUEUE 隊(duì)列。

例如,手動(dòng)執(zhí)行一次JOBTEST,看看是否向隊(duì)列中記錄信息,操作如下:

SQL> exec dbms_scheduler.run_job('JOBTEST');

PL/SQL procedure successfully completed.

執(zhí)行下列腳本,出隊(duì)數(shù)據(jù):

SQL> set serveroutput on

SQL> DECLARE

l_dequeue_options DBMS_AQ.dequeue_options_t;

l_message_properties DBMS_AQ.message_properties_t;

l_message_handle RAW(16);

l_queue_msg sys.scheduler$_event_info;

BEGIN

l_dequeue_options.consumer_name := 'TEST';


DBMS_AQ.dequeue(queue_name => 'SYS.SCHEDULER$_EVENT_QUEUE',

dequeue_options => l_dequeue_options,

message_properties => l_message_properties,

payload => l_queue_msg,

msgid => l_message_handle);

COMMIT;


DBMS_OUTPUT.put_line('event_type : ' || l_queue_msg.event_type);

DBMS_OUTPUT.put_line('object_owner : ' || l_queue_msg.object_owner);

DBMS_OUTPUT.put_line('object_name : ' || l_queue_msg.object_name);

DBMS_OUTPUT.put_line('event_timestamp: ' || l_queue_msg.event_timestamp);

DBMS_OUTPUT.put_line('error_code : ' || l_queue_msg.error_code);

DBMS_OUTPUT.put_line('event_status : ' || l_queue_msg.event_status);

DBMS_OUTPUT.put_line('log_id : ' || l_queue_msg.log_id);

DBMS_OUTPUT.put_line('run_count : ' || l_queue_msg.run_count);

DBMS_OUTPUT.put_line('failure_count : ' || l_queue_msg.failure_count);

DBMS_OUTPUT.put_line('retry_count : ' || l_queue_msg.retry_count);

END;

/

event_type : JOB_STARTED

object_owner : TEST

object_name : INSERT_TEST_TBL

event_timestamp: 25-AUG-09 12.49.29.558758 PM +08:00

error_code : 0

event_status : 1

log_id :

run_count : 1

failure_count : 0

retry_count : 0

PL/SQL procedure successfully completed.


從返回的信息可以看到,event 的類型為JOB_STARTED,表示JOB 啟動(dòng)。實(shí)際上job:JOBTEST執(zhí)行一次至少會(huì)向隊(duì)列中插入兩條event 信息,一條為JOB_STARTED,一條則為JOB_SUCCEEDED(也可能是JOB_FAILED),這里不詳細(xì)演示,感興趣的朋友不妨自行測(cè)試。

提示:SYS.SCHEDULER$_EVENT_QUEUE 隊(duì)列基于SYS.SCHEDULER$_EVENT_QTAB 隊(duì)列表,因此查詢

SYS.SCHEDULER$_EVENT_QTAB 也可以獲取上述的信息。

SYS.SCHEDULER$_EVENT_QUEUE 是一個(gè)固定隊(duì)列,實(shí)際應(yīng)用的過程中,DBA 應(yīng)該根據(jù)實(shí)際情況,將該表訪問權(quán)限授予相關(guān)用戶,以便順利出隊(duì)該隊(duì)列中的events 信息。

另外,友情提醒,默認(rèn)情況下Scheduler 僅保留最近24 小時(shí)的Events 信息,如果希望修改該設(shè)置的話,可

以通過SET_SCHEDULER_ATTRIBUTE 過程,修改scheduler 的event_expiry_time 屬性,該項(xiàng)屬性的屬性值以

秒為單位。


4.2 Application拋出的Events

首先要說明,這里所說的Application 是個(gè)代詞,即可以表示ORACLE 數(shù)據(jù)庫(kù)之外的應(yīng)用程序,也可以是ORACLE 數(shù)據(jù)庫(kù)中的PROCEDURE 等對(duì)象,總之你就將其理解成用戶自己創(chuàng)建的對(duì)象就好了。

Scheduler 能夠拋出Events 讓外部應(yīng)用處理,外部的應(yīng)用也可以拋出Events 讓Scheduler 啟動(dòng)job 處理,不過并不是任何job 都能夠?qū)ν獠繎?yīng)用拋出的Events 做出響應(yīng),必須在創(chuàng)建jobs 時(shí)明確指定響應(yīng)的事件。那么如何指定呢?依靠下列兩個(gè)附加的參數(shù):

  queue_spec:指定外部應(yīng)用拋出的events 消息入隊(duì)的隊(duì)列名;

  event_condition:指定觸發(fā)job 啟動(dòng)的條件,這一參數(shù)的參數(shù)值在設(shè)置時(shí)應(yīng)當(dāng)基于事件消息的自身屬性,因?yàn)槭录⒃谌腙?duì)時(shí),消息的屬性都是由application 定義的,因此在設(shè)置觸發(fā)條件時(shí),也應(yīng)該根據(jù)這些屬性值就行設(shè)置。


下面,我們就演示創(chuàng)建一個(gè)由event 觸發(fā)啟動(dòng)的job,在此之前,首先需要進(jìn)行一些準(zhǔn)備工具,比如創(chuàng)建隊(duì)列,由于隊(duì)列需要基于一個(gè)隊(duì)列表,因此在創(chuàng)建隊(duì)列之前,首先要?jiǎng)?chuàng)建一個(gè)隊(duì)列表,考慮到隊(duì)列表需要依賴一個(gè)對(duì)象類型,因此在創(chuàng)建隊(duì)列表之前,先得創(chuàng)建一個(gè)type.......復(fù)雜,具體的操作步驟如下:

SQL> create or replace type Test_type1 as object

2 (

3 event_type VARCHAR2(10),

4 object_owner VARCHAR2(30),

5 object_name VARCHAR2(30)

6 );

7 /

Type created.

SQL> begin

2 dbms_aqadm.create_queue_table(

3 queue_table => 'my_queue_tbl1',

4 queue_payload_type => 'Test_type1',

5 multiple_consumers => true);

6 end;

7 /

PL/SQL procedure successfully completed.

SQL> begin

2 dbms_aqadm.create_queue(

3 queue_name => 'event_t1',

4 queue_table => 'my_queue_tbl1');

5 end;

6 /

PL/SQL procedure successfully completed.

OK,準(zhǔn)備工作完成,下面就來(lái)創(chuàng)建一個(gè)event 觸發(fā)啟動(dòng)的job,創(chuàng)建腳本如下:

SQL> BEGIN

2 DBMS_SCHEDULER.CREATE_JOB (

3 job_name => 'EVENT_JOB_T1',

4 job_type => 'STORED_PROCEDURE',

5 job_action => 'SYSTEM.IT',

6 event_condition => 'tab.user_data.event_type = ''OP_INSERT''',

7 queue_spec => 'EVENT_T1',

8 enabled => TRUE);

9 END;

10 /

PL/SQL procedure successfully completed.


上述腳本僅做演示,因此創(chuàng)建的job 仍然執(zhí)行IT 過程。


通過pl/sql 直接向event_t1 隊(duì)列中添加消息的方式,觸發(fā)job 的啟動(dòng),具體操作如下。

首先要執(zhí)行DBMS_AQADM.START_QUEUE 過程,將event_t1 置于允許入隊(duì)和出隊(duì)狀態(tài)(默認(rèn)情況下創(chuàng)建的隊(duì)列是不允許出隊(duì)和入隊(duì)操作的),腳本如下:

SQL> exec dbms_aqadm.start_queue(queue_name => 'event_t1',enqueue => true,dequeue => true);

PL/SQL procedure successfully completed.

執(zhí)行入隊(duì)操作:

SQL> declare

v_Message Test_type1;

v_EnqueueOptions dbms_aq.enqueue_options_t;

v_MessageProperties dbms_aq.message_properties_t;

v_msg_handle raw(16);

begin

v_message := jss_type1('OP_SELECT', user, 'tmpObj');

dbms_aq.enqueue(queue_name => 'event_t1',

enqueue_options => v_enqueueOptions,

message_properties => v_messageproperties,

payload => v_message,

msgid => v_msg_handle);

commit;

end;

/

PL/SQL procedure successfully completed.


查詢隊(duì)列表中的數(shù)據(jù):

SQL> select user_data from my_queue_tbl1;

USER_DATA(EVENT_TYPE, OBJECT_OWNER, OBJECT_NAME)

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

JSS_TYPE1('OP_SELECT', 'TEST', 'tmpObj')

然后查詢job

SQL> select to_char(created,'yyyy-mm-dd hh24:mi:ss') from jss_1;

TO_CHAR(CREATED,'YY

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

2009-08-25 12:49:29

看起來(lái)jss_1 表中并未有新增加記錄,似乎job 沒有執(zhí)行啊。這很正常,還記得咱們創(chuàng)建job 時(shí)指定的event_condition 條件嗎:


6 event_condition => 'tab.user_data.event_type = ''OP_INSERT''',

沒錯(cuò),只有當(dāng)event_type 為'OP_INSERT'時(shí)才會(huì)觸發(fā)job 的執(zhí)行,前面入隊(duì)時(shí)指定的是OP_SELECT,當(dāng)然

沒有觸發(fā)job 中指定的procedure 啦,下面再次執(zhí)行入隊(duì)操作:

SQL> declare

v_Message jss_type1;

v_EnqueueOptions dbms_aq.enqueue_options_t;

v_MessageProperties dbms_aq.message_properties_t;

v_msg_handle raw(16);

begin

v_message := jss_type1('OP_INSERT', user, 'tmpObj');

dbms_aq.enqueue(queue_name => 'event_t1',

enqueue_options => v_enqueueOptions,

message_properties => v_messageproperties,

payload => v_message,

msgid => v_msg_handle);

commit;


end;

/

再次查看jss_1 表看看:

SQL> select to_char(created,'yyyy-mm-dd hh24:mi:ss') from jss_1;

TO_CHAR(CREATED,'YY

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

2009-08-25 12:49:29

2009-08-25 13:21:21

多了一條記錄,說明job 已經(jīng)被自動(dòng)觸發(fā)。

最后再補(bǔ)充一句,基于event 的job 不能通過DBMS_SCHEDULER.RUN_JOB 過程執(zhí)行,否則會(huì)觸發(fā)ORA-00942: table or view does not exist 錯(cuò)誤。


五、使用Chains

CHAIN(注意不要敲成CHINA) 可以被視做一組Programs 的復(fù)合,舉個(gè)簡(jiǎn)單的例子:運(yùn)行PROGRAM:A 以及PROGRAM:B,如果成功的話繼續(xù)運(yùn)行PROGRAM:C,否則的話運(yùn)行PROGRAM:D。Programs:A、B、C、D 以及執(zhí)行的邏輯關(guān)系就構(gòu)成了一個(gè)最簡(jiǎn)單的CHAIN。

關(guān)于CHAIN 的管理操作比較多,比如創(chuàng)建/刪除/修改Chains,添加/修改/刪除Chain Steps 等等。

5.1 創(chuàng)建Chains

5.1.1 創(chuàng)建CHAIN對(duì)象

創(chuàng)建CHAIN 使用DBMS_SCHEDULER.CREATE_CHAIN 過程,這個(gè)過程調(diào)用非常簡(jiǎn)單,因?yàn)樾枰付ǖ?/p>

參數(shù)極少,該過程的定義如下:

SQL> desc dbms_scheduler.create_chain;

Parameter Type Mode Default?

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

CHAIN_NAME VARCHAR2 IN

RULE_SET_NAME VARCHAR2 IN Y

EVALUATION_INTERVAL INTERVAL DAY TO SECOND IN Y

COMMENTS VARCHAR2 IN Y

在創(chuàng)建時(shí),甚至可以簡(jiǎn)單到只指定一個(gè)CHAIN 的名稱,其它均為空即可,例如:

SQL> exec dbms_scheduler.create_chain('my_chain1');

PL/SQL procedure successfully completed.

定義好的Chains,可以通過*_SCHEDULER_CHAINS 視圖查看,例如:

SQL> select chain_name from user_scheduler_chains;

CHAIN_NAME

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

MY_CHAIN1

注意,不是說創(chuàng)建了CHAIN 就齊活,只有一個(gè)CHAIN 對(duì)象ORACLE 還是啥也干不了(當(dāng)然啦,相信從上面執(zhí)行的創(chuàng)建語(yǔ)句大家也看出來(lái)了),CHAIN 對(duì)象創(chuàng)建之后,要做的工作其實(shí)才剛剛開始。其后,還需要定義ChainSteps 以及Chain rules。

5.1.2 創(chuàng)建Chain Step

Chain Steps 就是用來(lái)指定CHAIN 執(zhí)行的操作及執(zhí)行步驟, 創(chuàng)建CHAIN STEP 是通過

DBMS_SCHEDULER.DEFINE_CHAIN_STEP 過程進(jìn)行,例如,為剛剛創(chuàng)建的my_chain1 添加一個(gè)step,執(zhí)行操作如下:

SQL> begin

DBMS_SCHEDULER.DEFINE_CHAIN_STEP (

chain_name => 'my_chain1',

step_name => 'my_step1',

program_name => 'p_p1');

end;

/

PL/SQL procedure successfully completed.

Chain Steps 即可以調(diào)用PROGRAM(注意是program,不是procedure,當(dāng)然program 中可以定義執(zhí)行procedure),也可以調(diào)用EVENT,甚至調(diào)用其它CHAIN(這就叫嵌套CHAIN)。

下面接著為my_chain1 添加兩個(gè)step,操作如下:

SQL> begin

DBMS_SCHEDULER.DEFINE_CHAIN_STEP (

chain_name => 'my_chain1',

step_name => 'my_step2',

program_name => 'p_p2');

DBMS_SCHEDULER.DEFINE_CHAIN_STEP (

chain_name => 'my_chain1',

step_name => 'my_step3',

program_name => 'p_p3');

end;

/

PL/SQL procedure successfully completed.

要查詢定義的Chain Steps,則是通過*_SCHEDULER_CHAIN_STEPS 視圖,例如:

SQL> select chain_name,step_name,program_name from user_scheduler_chain_steps;

CHAIN_NAME STEP_NAME PROGRAM_NAME

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

MY_CHAIN1 MY_STEP1 P_P1

MY_CHAIN1 MY_STEP2 P_P2

MY_CHAIN1 MY_STEP3 P_P3


5.1.3 創(chuàng)建Chain Rule

接下來(lái),要為CHAIN 的運(yùn)行定義規(guī)則。定義規(guī)則是使用DBMS_SCHEDULER.DEFINE_CHAIN_RULE 過程,Chain Rules 依賴于Chain Steps,每個(gè)CHAIN RULE 都擁有condition 和action 屬性,當(dāng)滿足condition 時(shí)則執(zhí)行action 中指定的step。

DBMS_SCHEDULER.DEFINE_CHAIN_RULE 過程的語(yǔ)法如下:

SQL> desc dbms_scheduler.define_chain_rule;

Parameter Type Mode Default?

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

CHAIN_NAME VARCHAR2 IN

CONDITION VARCHAR2 IN

ACTION VARCHAR2 IN

RULE_NAME VARCHAR2 IN Y

COMMENTS VARCHAR2 IN Y

CHAIN_NAME 就不說了,需要注意的是CONDITION 和ACTION 兩個(gè)參數(shù)。在為condition 參數(shù)指定值時(shí),其語(yǔ)法看起來(lái)稍稍復(fù)雜一些,或者說是靈活,condition 參數(shù)值支持下列的語(yǔ)法形式:

TRUE

FALSE

stepname [NOT] SUCCEEDED

stepname [NOT] FAILED

stepname [NOT] STOPPED

stepname [NOT] COMPLETED

stepname ERROR_CODE IN (integer, integer, integer ...)

stepname ERROR_CODE NOT IN (integer, integer, integer ...)

stepname ERROR_CODE = integer

stepname ERROR_CODE != integer

stepname ERROR_CODE <> integer

stepname ERROR_CODE > integer

stepname ERROR_CODE >= integer

stepname ERROR_CODE < integer

stepname ERROR_CODE <= integer

甚至于,還可以制定成下列邏輯語(yǔ)法:

expression AND expression

expression OR expression

NOT (expression)

比如說,我們希望條件為step1 成功運(yùn)行,那么可以指定condition 參數(shù)值如下:

'step1 completed'

Action 參數(shù)相對(duì)簡(jiǎn)單一些,這個(gè)參數(shù)用來(lái)指定當(dāng)滿足condition 參數(shù)時(shí),CHAIN 執(zhí)行的操作。

例如,創(chuàng)建CHAIN RULE,首先執(zhí)行my_step1,如果my_step1 成功執(zhí)行的話,就繼續(xù)執(zhí)行my_step2,如

果my_step2 也成功執(zhí)行的話,則結(jié)束該CHAIN,創(chuàng)建腳本如下:

SQL> BEGIN

DBMS_SCHEDULER.DEFINE_CHAIN_RULE (

chain_name => 'my_chain1',

condition => 'TRUE',

action => 'START my_step1',

rule_name => 'my_rule1');

DBMS_SCHEDULER.DEFINE_CHAIN_RULE (

chain_name => 'my_chain1',

condition => 'my_step1 completed',

action => 'START my_step2',

rule_name => 'my_rule2');

DBMS_SCHEDULER.DEFINE_CHAIN_RULE (

chain_name => 'my_chain1',

condition => 'my_step2 completed',

action => 'end 0',

rule_name => 'my_rule3');

END;

/

PL/SQL procedure successfully completed.


5.1.4 運(yùn)行Chains

最后,來(lái)運(yùn)行一下創(chuàng)建的my_chain1 吧,手動(dòng)運(yùn)行CHAIN 是通過DBMS_SCHEDULER.RUN_CHAIN 過程,

例如:

SQL> BEGIN

DBMS_SCHEDULER.RUN_CHAIN (

chain_name => 'my_chain1',

start_steps => 'my_step1');

END;

/

PL/SQL procedure successfully completed.

語(yǔ)句執(zhí)行成功,下面需要查看一下執(zhí)行的結(jié)果。我們之前定義的p_p1 等program 對(duì)象,實(shí)際上是調(diào)用procedure,向一個(gè)指定表jss_t2 中插入記錄,這里直接查詢一下該表,就知道執(zhí)行情況了(在此之前,jss_t2 表為空):

SQL> select * from jss_t2;

TP DT

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

p_p1 inserted 03-SEP-09

p_p2 inserted 03-SEP-09

你看,jss_t2 表中有了兩條記錄,對(duì)應(yīng)前面設(shè)置的CHAIN RULE,說明my_step1 和my_step2 均已正確執(zhí)行。提示:Chains 在執(zhí)行前,必須被置于enabled 狀態(tài),默認(rèn)情況下剛剛創(chuàng)建的CHAIN 都是disabled 狀態(tài),要修改Chains 的狀態(tài),還是通過DBMS_SCHEDULER.ENABLE 和DBMS_SCHEDULER.DISABLE 兩過程,這里就不演示了。手動(dòng)執(zhí)行的CHAIN 的話沒有系統(tǒng)級(jí)的日志記錄,因此如果希望看到詳細(xì)執(zhí)行情況的話,建議創(chuàng)建job 來(lái)執(zhí)行CHAIN,例如:


SQL> BEGIN

DBMS_SCHEDULER.CREATE_JOB (

job_name => 'chain_job_1',

job_type => 'CHAIN',

job_action => 'my_chain1',

repeat_interval => 'freq=daily;interval=1',

enabled => TRUE);

END;

/

PL/SQL procedure successfully completed.

然后,dba 就可以通過定期觀察*_scheduler_job_run_details 視圖來(lái)確認(rèn)chain 的執(zhí)行情況了。


5.2 管理Chains

5.2.1 修改Chains屬性

基本上碰到修改CHAIN 屬性的機(jī)率不會(huì)太大,因此確實(shí)沒啥可修改的,對(duì)于CHAIN 對(duì)象來(lái)說,能夠修改的屬性只有兩個(gè):evaluation_interval 和comments,這兩個(gè)參數(shù)一般情況下甚至都不會(huì)進(jìn)行設(shè)置。如果你碰到了確實(shí)需要修改的情況,沒問題,DBMS_SCHEDULER.SET_ATTRIBUTE 過程還記的吧,沒錯(cuò),修改CHAIN 也是用它。例如:

SQL> select chain_name,comments from user_scheduler_chains;

CHAIN_NAME COMMENTS

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

MY_CHAIN1

SQL> exec dbms_scheduler.set_attribute('my_chain1','comments','change it for a test!');

PL/SQL procedure successfully completed.

SQL> select chain_name,comments from user_scheduler_chains;

CHAIN_NAME COMMENTS

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

MY_CHAIN1 change it for a test !


5.2.2 設(shè)置Chain Step運(yùn)行屬性

修改Chain Step 的運(yùn)行屬性就不能使用DBMS_SCHEDULER.SET_ATTRIBUTE 了,而是有專門的過程

DBMS_SCHEDULER.ALTER_CHAIN 處理,該過程的定義如下:

SQL> desc dbms_scheduler.alter_chain;

Parameter Type Mode Default?

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

CHAIN_NAME VARCHAR2 IN

STEP_NAME VARCHAR2 IN

ATTRIBUTE VARCHAR2 IN

VALUE BOOLEAN IN

前兩個(gè)參數(shù)就不說了,ATTRIBUTE 參數(shù)用來(lái)指定STEP 的屬性值,可設(shè)定的屬性值有3 個(gè),每個(gè)屬性值都

有TRUE 和FALSE 兩個(gè)選項(xiàng),由VALUE 參數(shù)指定:

   PAUSE:設(shè)置該參數(shù)值為TRUE 時(shí),當(dāng)step 運(yùn)行時(shí),其運(yùn)行狀態(tài)就會(huì)變更為PAUSED;

   SKIP:設(shè)置該參數(shù)值為TRUE 時(shí),當(dāng)step 滿足運(yùn)行條件時(shí),并不是執(zhí)行step 中的program,而是直接跳過,注意當(dāng)SKIP 參數(shù)值設(shè)置為TRUE,并且PAUSE 參數(shù)值也被設(shè)置為TRUE,那么將會(huì)以PAUSE 的狀態(tài)優(yōu)先;

   RESTART_ON_RECOVERY:設(shè)置該參數(shù)值為TRUE 時(shí),如果由于數(shù)據(jù)庫(kù)shutdown 導(dǎo)致step 被停止,那么當(dāng)下次數(shù)據(jù)庫(kù)啟動(dòng)時(shí),step 會(huì)自動(dòng)重新運(yùn)行。

DBMS_SCHEDULER.ALTER_CHAIN 過程修改Chain Step 屬性后,只有當(dāng)下次運(yùn)行時(shí)才會(huì)生效,如果要修改當(dāng)前運(yùn)行中Chain Step 的屬性,也有一個(gè)專門的過程DBMS_SCHEDULER.ALTER_RUNNING_CHAIN 進(jìn)行處理,該過程語(yǔ)法與DBMS_SCHEDULER.ALTER_CHAIN 一模一樣,這里就不詳細(xì)介紹了。


5.2.3 刪除Chain Rules

Chain Rules 沒有對(duì)應(yīng)的修改方法,如果要修改某個(gè)Chain 的rule,只能首先刪除不適當(dāng)?shù)膔ule,然后重新添加新rule(所謂添加,其實(shí)就是再重新定義一個(gè)rule)。

刪除Chain Rule 有專門的過程DBMS_SCHEDULER.DROP_CHAIN_RULE,該過程語(yǔ)法如下:

SQL> desc dbms_scheduler.drop_chain_rule;

Parameter Type Mode Default?

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

CHAIN_NAME VARCHAR2 IN

RULE_NAME VARCHAR2 IN

FORCE BOOLEAN IN Y

舉個(gè)簡(jiǎn)單的示例,比如刪除前面定義的my_rule3,執(zhí)行過程如下:

SQL> exec dbms_scheduler.drop_chain_rule('my_chain1','my_rule3',true);

PL/SQL procedure successfully completed.


5.2.4 刪除Chain Steps

刪除Chain Step 也有專門的過程DBMS_SCHEDULER.DROP_CHAIN_STEP 進(jìn)行處理,該過程語(yǔ)法如下:

SQL> desc dbms_scheduler.drop_chain_step;

Parameter Type Mode Default?

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

CHAIN_NAME VARCHAR2 IN

STEP_NAME VARCHAR2 IN

FORCE BOOLEAN IN Y

看著有點(diǎn)兒眼熟是吧,沒錯(cuò),與drop_chain_rule 的相似度高達(dá)90%以上。例如,刪除之前定義的my_step3,

執(zhí)行過程如下:

SQL> exec dbms_scheduler.drop_chain_step('my_chain1','my_step3',true);

PL/SQL procedure successfully completed.


5.2.5 刪除Chains

如果要?jiǎng)h除Chain 那就更簡(jiǎn)單了,執(zhí)行dbms_scheduler.drop_chain 過程即可,例如:

SQL> exec dbms_scheduler.drop_chain('my_chain1',true);

PL/SQL procedure successfully completed.

注意,執(zhí)行drop_chain 時(shí),如果不指定force 參數(shù)為TRUE,那么默認(rèn)情況下ORACLE 會(huì)首先檢查要?jiǎng)h除的CHAIN 是否還有被依賴的對(duì)象,如果存在的話,會(huì)報(bào)ORA-27479 錯(cuò)誤,提示仍然有依賴的對(duì)象(所謂依賴的對(duì)象就是指,該chain 仍然存在chain_step 或chain_rule 之類),因此無(wú)法直接刪除。這種情況下解決方案有兩種:

一是手動(dòng)刪除所有相關(guān)的chain_step 和chain_rule,然后再執(zhí)行chain 的刪除,再就是附加force 參數(shù)并指定參數(shù)

值為true,這樣ORACLE 就會(huì)自動(dòng)替你清除所有依賴的對(duì)象了。

 

六、使用Job Classes

Job Classes 相當(dāng)于創(chuàng)建了一個(gè)job 組,DBA 可以將那些具有相同特性的job,統(tǒng)統(tǒng)放到相同的Job Classes中,然后通過對(duì)Job Class 應(yīng)用ORACLE 中的"資源使用計(jì)劃"特性,就可以對(duì)這些job 執(zhí)行過程中所需要的資源分配情況進(jìn)行管理。

1、創(chuàng)建Job Classes

使用DBMS_SCHEDULER 包的CREATE_JOB_CLASS 過程創(chuàng)建Job Classes,該過程支持的參數(shù)如下:

SQL> desc dbms_scheduler.create_job_class;

Parameter Type Mode Default?

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

JOB_CLASS_NAME VARCHAR2 IN

RESOURCE_CONSUMER_GROUP VARCHAR2 IN Y

SERVICE VARCHAR2 IN Y

LOGGING_LEVEL BINARY_INTEGER IN Y

LOG_HISTORY BINARY_INTEGER IN Y

COMMENTS VARCHAR2 IN Y

其中:

JOB_CLASS_NAME:要?jiǎng)?chuàng)建的Job Class 的名稱,注意指定的長(zhǎng)度不要超過30 個(gè)字符,也不要與現(xiàn)有Job Class 同名;

RESOURCE_CONSUMER_GROUP:指定創(chuàng)建的Job Class 所在的RCG;

提示:啥是Resource Consumer Group

你可以將其理解成一個(gè)資源分配的方式,處于相同RCG 組中的用戶、會(huì)話、或者對(duì)象共用一組資源,這組資源中可供分配的資源按照DBA 指定的方式分配給RCG。如果設(shè)計(jì)合理,通過這種方式,可以更有效的利用服務(wù)器的資源。

SERVICE:指定創(chuàng)建的Job Class 所在Service,本選項(xiàng)常見于RAC 環(huán)境,我們都知道RAC 環(huán)境由多實(shí)例+數(shù)據(jù)庫(kù)組成,此處所指定的Service 實(shí)際就是指Job Class 會(huì)在哪個(gè)實(shí)例上運(yùn)行。

注意:本參數(shù)與RESOURCE_CONSUMER_GROUP 參數(shù)相互沖突,同一個(gè)Job Class 只同設(shè)置兩個(gè)參數(shù)中的一個(gè)值。

   LOGGING_LEVEL:指定日志記錄的級(jí)別,有下列三種級(jí)別:

   DBMS_SCHEDULER.LOGGING_OFF:關(guān)閉日志記錄功能;

   DBMS_SCHEDULER.LOGGING_RUNS:對(duì)該Job Class 下所有任務(wù)的運(yùn)行信息進(jìn)行記錄;

   DBMS_SCHEDULER.LOGGING_FULL:記錄該Job Class 下任務(wù)的所有相關(guān)信息,不僅有任務(wù)的運(yùn)行情況,甚至連任務(wù)的創(chuàng)建、修改等也均將記入日志。

   LOG_HISTORY:指定日志記錄的時(shí)間,以天為單位,比如指定LOG_HISTORY 參數(shù)值為90,就表示日志信息保留最近90 天的內(nèi)容。

   COMMENTS:指定注釋信息。


上述各個(gè)參數(shù),除了LOG_CLASS_NAME 參數(shù)為必選參外,其它均為可選參數(shù),例如:

SQL> EXEC DBMS_SCHEDULER.CREATE_JOB_CLASS('my_first_jc');

PL/SQL procedure successfully completed


查詢系統(tǒng)中已經(jīng)存在的Job Classes .可以通過DBA_SCHEDULER_JOB_CLASSES視圖( 或ALL_SCHEDULER_JOB_CLASS 視圖)


當(dāng)創(chuàng)建Jobs 時(shí),可以通過JOB_CLASS 參數(shù)來(lái)指定job 所在的Job Class,如果不指定的話,創(chuàng)建的job 默認(rèn)屬于DEFAULT_JOB_CLASS 。至于說如何查詢創(chuàng)建的jobs 屬于哪個(gè)Job Class , 還用說嗎,*_SCHEDULER_JOBS 視圖中的JOB_CLASS 列唄。


2、管理Job Classes

DBMS_SCHEDULER.SET_ATTRIBUTE 過程大家應(yīng)當(dāng)還記的,前面的小節(jié)中演示中使用該過程,修改job的屬性,實(shí)際上SET_ATTRIBUTE 也同樣可以用來(lái)修改Job Class 的屬性,操作方法與修改job 屬性完全相同,只不過作用函概的范圍更廣,修改Job Class 后,該Job Class 下屬的所有job 屬性都會(huì)被級(jí)聯(lián)修改(當(dāng)前正運(yùn)行的不會(huì)立刻生效,將等到下次運(yùn)行時(shí)生效)。


例如:修改剛剛創(chuàng)建的MY_FIRST_JC 的日志保存時(shí)間:

SQL> EXEC DBMS_SCHEDULER.SET_ATTRIBUTE('SYS.MY_FIRST_JC','LOG_HISTORY','30');

PL/SQL procedure successfully completed.

提示:Job Class 可被修改的屬性,即創(chuàng)建時(shí)可選擇指定的那5 個(gè)屬性。


3、刪除Job Classes

DBMS_SCHEDULER 包提供了DROP_JOB_CLASS 過程,用來(lái)刪除Job Classes。該過程調(diào)用非常簡(jiǎn)單,例

如,刪除剛剛創(chuàng)建的MY_FIRST_JC,執(zhí)行命令如下:

JSSWEB> EXEC DBMS_SCHEDULER.DROP_JOB_CLASS('MY_FIRST_JC');

PL/SQL procedure successfully completed.

如果有多個(gè)Job Classes 需要?jiǎng)h除,并不需要多次執(zhí)行DROP_JOB_CLASS,只需要在為該過程指定值時(shí),參數(shù)值間以逗號(hào)分隔即可。

 

七、使用Windows

此Windows 非彼Windows,通常說的Windows 是指蓋首富的操作系統(tǒng),而此處所說的Windows,是指SCHEDULER 特性中的一個(gè)子項(xiàng)。在SCHEDULER 中,WINDOW 對(duì)應(yīng)的是一個(gè)時(shí)間窗口的概念。我們知道普通的jobs 是沒有運(yùn)行時(shí)間管理地概念的,就是說一個(gè)job 啟動(dòng)之后,用戶只能被動(dòng)地等待其執(zhí)行,一直到其執(zhí)行地任務(wù)完成(或DBA 手動(dòng)kill 對(duì)應(yīng)進(jìn)程),在此期間,執(zhí)行的job 將與其它活動(dòng)的進(jìn)程共同競(jìng)爭(zhēng)當(dāng)前系統(tǒng)中的資源。對(duì)于大型數(shù)據(jù)庫(kù)系統(tǒng),系統(tǒng)資源那可是相當(dāng)寶貴的無(wú)形資產(chǎn)哪,企能誰(shuí)說用就用、想什么時(shí)候用就什么時(shí)候用,沒點(diǎn)兒計(jì)劃沒點(diǎn)兒節(jié)制這還了得。你還別說,在9i 之前,還真就是這么回事兒,誰(shuí)想用就用,誰(shuí)也管不了,其中表示最甚的就是job。你是否想起了Job Classes,沒錯(cuò)定義Job Classes 確實(shí)可以控制job 能夠使用的資源,不過單單使用Job Classes 并不能靈活的控制job 在合適的時(shí)間使用適當(dāng)?shù)馁Y源。進(jìn)入10g之后,SCHEDULER 中提供了WINDOW,事情終于有了緩解。WINDOW 可以指定一個(gè)時(shí)間窗口,在此期間,通過與Job Classes 的搭配組合,能夠有效控制job 執(zhí)行時(shí)支配(使用)的資源。比如說job 通常是在凌晨服務(wù)器負(fù)載較低時(shí)執(zhí)行,那么就可以通過WINDOW 設(shè)置在此期間,允許jobs 使用更多的系統(tǒng)資源,而到了工作時(shí)間后,如果job 仍未執(zhí)行完成,為其分配另一個(gè)有限的資源,以盡可能降低job 執(zhí)行占用的資源對(duì)其它業(yè)務(wù)的影響。


1、創(chuàng)建Window

創(chuàng)建Window 有一個(gè)專門的過程:DBMS_SCHEDULER.CREATE_WINDOW 進(jìn)行處理,該過程有兩種調(diào)用方式,如下:

--基于SCHEDULE

DBMS_SCHEDULER.CREATE_WINDOW (

window_name IN VARCHAR2,

resource_plan IN VARCHAR2,

schedule_name IN VARCHAR2,

duration IN INTERVAL DAY TO SECOND,

window_priority IN VARCHAR2 DEFAULT 'LOW',

comments IN VARCHAR2 DEFAULT NULL);

--基于定義的調(diào)度

DBMS_SCHEDULER.CREATE_WINDOW (

window_name IN VARCHAR2,

resource_plan IN VARCHAR2,

start_date IN TIMESTAMP WITH TIME ZONE DEFAULT NULL,

repeat_interval IN VARCHAR2,

end_date IN TIMESTAMP WITH TIME ZONE DEFAULT NULL,

duration IN INTERVAL DAY TO SECOND,

window_priority IN VARCHAR2 DEFAULT 'LOW',

comments IN VARCHAR2 DEFAULT NULL);


刨開那些看著眼熟的,已經(jīng)認(rèn)識(shí)的,看參數(shù)名就知道其所代表含義的之外,下列幾個(gè)參數(shù)可能需要關(guān)注:

   Resource_plan:這一參數(shù)用來(lái)指定要使用的資源使用計(jì)劃,當(dāng)打開WINDOW 時(shí),就會(huì)自動(dòng)按照指定的資源使用計(jì)劃中的設(shè)置分配資源,當(dāng)WINDOW 關(guān)閉時(shí)(沒錯(cuò),window 是會(huì)關(guān)閉的,要不怎么說有效控制資源的使用情況泥),系統(tǒng)會(huì)自動(dòng)切換回適當(dāng)資源計(jì)劃。這個(gè)參數(shù)在執(zhí)行過程時(shí)甚至可以指定為NULL 或空值'',當(dāng)設(shè)置為NULL 時(shí),就表示使用默認(rèn)的資源計(jì)劃,當(dāng)設(shè)置為空值''時(shí),表示禁用資源使用計(jì)劃。

   Duration:指定WINDOW 的有效期,比如說指定為interval '5' hour 就表示5 個(gè)小時(shí),該參數(shù)在執(zhí)行過程時(shí)必須指定參數(shù)值,否則創(chuàng)建會(huì)報(bào)錯(cuò)。

   Window_priority:該參數(shù)用來(lái)指定WINDOW 的優(yōu)先級(jí)。因?yàn)樵谙嗤瑫r(shí)間只有一個(gè)WINDOW 有效,因此如果在創(chuàng)建WINDOW 時(shí)發(fā)現(xiàn)重疊的情況,ORACLE 就需要根據(jù)這一參數(shù)指定的規(guī)則,來(lái)確定優(yōu)先級(jí),說白了就是先把資源給誰(shuí)用,這一參數(shù)有兩個(gè)可選值:HIGH 或LOW,默認(rèn)值為L(zhǎng)OW。


正如前面CREATE_WINDOW 過程語(yǔ)法結(jié)構(gòu)顯示的那樣,調(diào)用該過程有兩種方式,差異就在于是指定現(xiàn)有定義好的調(diào)度SCHEDULE,還是在執(zhí)行過程時(shí)指定調(diào)度,目標(biāo)和實(shí)現(xiàn)的功能都是相同的,這里僅做示例,咱就挑個(gè)最復(fù)雜的方式吧,執(zhí)行過程時(shí)指定調(diào)度,執(zhí)行腳本如下:


SQL> begin

dbms_scheduler.create_window(

window_name => 'my_first_wd1',

resource_plan => null,

start_date => sysdate,

repeat_interval => 'FREQ=DAILY; INTERVAL=5',

duration => interval '1' hour);

end;

/

PL/SQL procedure successfully completed.


查詢當(dāng)前擁有的WINDOW,可以通過*_SCHEDULER_WINDOWS視圖(注意只有DBA 和ALL,沒有USER,因?yàn)樗卸x的WINDOW 都屬于SYS 用戶)。除了*_SCHEDULER_WINDOWS 視圖顯示當(dāng)前所有WINDOW外,還有:

     *_SCHEDULER_WINDOW_DETAILS 視圖:顯示W(wǎng)INDOW 的詳細(xì)信息;

   *_SCHEDULER_WINDOW_LOG 視圖:顯示W(wǎng)INDOW 的日志,比如打開和關(guān)閉;


2、管理Window

通過前面那些SCHEDULER 對(duì)象的學(xué)習(xí),相當(dāng)大家已經(jīng)了解了ORACLE SCHEDULER 中對(duì)象的特點(diǎn),對(duì)于多數(shù)對(duì)象的管理,不外乎下列幾種:

修改對(duì)象屬性,使用SET_ATTRIBUTE 過程;

SQL> exec dbms_scheduler.set_attribute('sys.my_first_wd1','start_date',sysdate+1);

PL/SQL procedure successfully completed.


ENABLE 對(duì)象,使用ENABLE 過程;

SQL> exec dbms_scheduler.enable('sys.my_first_wd1');

PL/SQL procedure successfully completed.


DISABLE 對(duì)象,使用DISABLE 過程;

SQL> exec dbms_scheduler.disable('sys.my_first_wd1');

PL/SQL procedure successfully completed.


刪除對(duì)象,使用DROP_WINDOW 過程;

SQL> exec dbms_scheduler.drop_window('sys.my_first_wd1');

PL/SQL procedure successfully completed.


除此之外呢,對(duì)于WINDOW 對(duì)象來(lái)說,由于其特殊作用,又有:手動(dòng)打開WINDOW,使用OPEN_WINDOW 過程;

注意WINDOW 是依賴于其調(diào)度的,因此在手動(dòng)打開WINDOW 時(shí),必須為其指定duration 屬性:

SQL> exec dbms_scheduler.open_window('sys.my_first_wd1',interval '1' hour);;

PL/SQL procedure successfully completed.

   手動(dòng)關(guān)閉WINDOW,使用CLOSE_WINDOW 過程;

SQL> exec dbms_scheduler.close_window('sys.my_first_wd1');

PL/SQL procedure successfully completed.

關(guān)閉和打開WINDOW,都會(huì)記錄日志,大家可以通過*_SCHEDULER_WINDOW_LOG 視圖中獲取這部分

信息。


3、關(guān)于WINDOWGROUP

除了WINDOW 外,還有一個(gè)與WINDOW 有關(guān)系的叫WINDOW GROUP,一個(gè)WINDOW GROUP 可能包含多個(gè)WINDOW。使用WINDOW GROUP 的本意是這樣的,假如說某個(gè)job 執(zhí)行的時(shí)間比較長(zhǎng),甚至全天24小時(shí)都在執(zhí)行,對(duì)于這類job,單個(gè)WINDOW 很難有效調(diào)整其資源占用,這時(shí)間呢,就可以通過設(shè)置一個(gè)WINDOW GROUP,該WINDOW GROUP 中包含了多個(gè)WINDOW,每個(gè)WINDOW 分別負(fù)責(zé)不同時(shí)間點(diǎn)時(shí)的資源使用計(jì)劃。

然后在創(chuàng)建JOB 時(shí),指定schedule_name 參數(shù)為WINDOW GROUP 的名稱(想不到SCHEDULE_NAME 還能指定為WINDOW GROUP 哪,其實(shí)何止WINDOW GROUP,還可以直接指定成WINDOW 哪),這樣,就可以通過很簡(jiǎn)單的方式,將job 與window 聯(lián)系在一起了。


WINDOW GROUP 的創(chuàng)建和管理與前面介紹的方式極其相似:

   創(chuàng)建,使用CREATE_WINDOW_GROUP 過程;

   刪除,使用DROP_WINDOW_GROUP 過程;

   添加WINDOW 成員,使用ADD_WINDOW_GROUP_MEMBER 過程;

   刪除WINDOW 成員,使用REMOVE_WINDOW_GROUP_MEMBER 過程;

   啟用,使用ENABLE 過程;

   禁用,使用DISABLE 過程;

這些過程的調(diào)用方式也都非常簡(jiǎn)單,這里就不著重演示了,感興趣的朋友不妨自行嘗試。

 

本文來(lái)自CSDN博客,轉(zhuǎn)載請(qǐng)標(biāo)明出處:http://blog.csdn.net/tianlesoftware/archive/2009/10/22/4715218.aspx