oracle定時(shí)任務(wù)詳解(轉(zhuǎn)自CSDN)
DBMS_JOB系統(tǒng)包是Oracle“任務(wù)隊(duì)列”子系統(tǒng)的API編程接口。DBMS_JOB包對(duì)于任務(wù)隊(duì)列提供了下面這些功能:提交并且執(zhí)行一個(gè)任務(wù)、改變?nèi)蝿?wù)的執(zhí)行參數(shù)以及刪除或者臨時(shí)掛起任務(wù)等。
DBMS_JOB包是由ORACLE_HOME目錄下的rdbms/admin子目錄下的DBMSJOB.SQL和PRVTJOB.PLB 這兩個(gè)腳本文件創(chuàng)建的。這兩個(gè)文件被CATPROC.SQL腳本文件調(diào)用,而CATPROC.SQL這個(gè)文件一般是在數(shù)據(jù)庫創(chuàng)建后立即執(zhí)行的。腳本為DBMS_JOB包創(chuàng)建了一個(gè)公共同義詞,并給該包授予了公共的可執(zhí)行權(quán)限,所以所有的Oracle用戶均可以使用這個(gè)包。
下面幾個(gè)數(shù)據(jù)字典視圖是關(guān)于任務(wù)隊(duì)列信息的,主要有DBA_JOBS, USER_JOBS和DBA_JOBS_RUNNING。這些字典視圖是由名為CATJOBQ.SQL的腳本文件創(chuàng)建的。該腳本文件和創(chuàng)建DBMS_JOB包的腳本文件一樣在ORACLE_HOME目錄的rdbms/admin子目錄中,同樣也是由腳本文件CATPROC.SQL調(diào)用。
最后,要使任務(wù)隊(duì)列能正常運(yùn)行,還必須啟動(dòng)它自己專有的后臺(tái)過程。啟動(dòng)后臺(tái)過程是通過在初始化文件init*.ora(實(shí)例不同,初始化文件名也略有不同)中設(shè)置初始化參數(shù)來進(jìn)行的。下面就是該參數(shù):
JOB_QUEUE_PROCESSES = n
其中,n可以是0到36之間的任何一個(gè)數(shù)。除了該參數(shù)以外,還有幾個(gè)關(guān)于任務(wù)隊(duì)列的初始化參數(shù),本文后面將會(huì)對(duì)其進(jìn)行詳細(xì)討論。
DBMS_JOB包中包含有許多過程,見表1所示。
表1 DBMS_JOB包
名稱 | 類型 | 描述 |
DBMS_JOB.ISUBMIT | 過程 | 提交一個(gè)新任務(wù),用戶指定一個(gè)任務(wù)號(hào) |
DBMS_JOB.SUBMIT | 過程 | 提交一個(gè)新任務(wù),系統(tǒng)指定一個(gè)任務(wù)號(hào) |
DBMS_JOB.REMOVE | 過程 | 從隊(duì)列中刪除一個(gè)已經(jīng)存在的任務(wù) |
DBMS_JOB.CHANGE | 過程 | 更改用戶設(shè)定的任務(wù)參數(shù) |
DBMS_JOB.WHAT | 過程 | 更改PL/SQL任務(wù)定義 |
DBMS_JOB.NEXT_DATE | 過程 | 更改任務(wù)下一次運(yùn)行時(shí)間 |
DBMS_JOB.INTERVAL | 過程 | 更改任務(wù)運(yùn)行的時(shí)間間隔 |
DBMS_JOB.BROKEN | 過程 | 將任務(wù)掛起,不讓其重復(fù)運(yùn)行 |
DBMS_JOB.RUN | 過程 | 在當(dāng)前會(huì)話中立即執(zhí)行任務(wù) |
DBMS_JOB.USER_EXPORT | 過程 | 創(chuàng)建文字字符串,用于重新創(chuàng)建一個(gè)任務(wù) |
三、DBMS_JOB包參數(shù)
DBMS_JOB包中所有的過程都有一組相同的公共參數(shù),用于定義任務(wù),任務(wù)的運(yùn)行時(shí)間以及任務(wù)定時(shí)運(yùn)行的時(shí)間間隔。這些公共任務(wù)定義參數(shù)見表2所示。
表2 DBMS_JOB過程的公共參數(shù)
名稱 | 類型 | 注釋 |
Job | BINARY_INTEGER | 任務(wù)的唯一識(shí)別號(hào) |
What | VARCHAR2 | 作為任務(wù)執(zhí)行的PL/SQL代碼 |
Next_date | VARCHAR2 | 任務(wù)下一次運(yùn)行的時(shí)間 |
Interval | VARCHAR2 | 日期表達(dá)式,用來計(jì)算下一次任務(wù)運(yùn)行的時(shí)間 |
下面我們來詳細(xì)討論這些參數(shù)的意義及用法。
1、job
參數(shù)job是一個(gè)整數(shù),用來唯一地標(biāo)示一個(gè)任務(wù)。該參數(shù)既可由用戶指定也可由系統(tǒng)自動(dòng)賦予,這完全取決于提交任務(wù)時(shí)選用了那一個(gè)任務(wù)提交過程。DBMS_JOB.SUBMIT過程通過獲得序列SYS.JOBSEQ的下一個(gè)值來自動(dòng)賦予一個(gè)任務(wù)號(hào)。該任務(wù)號(hào)是作為一個(gè)OUT參數(shù)返回的,所以調(diào)用者隨后可以識(shí)別出提交的任務(wù)。而DBMS_JOB.ISUBMIT過程則由調(diào)用者給任務(wù)指定一個(gè)識(shí)別號(hào),這時(shí)候,任務(wù)號(hào)的唯一性就完全取決于調(diào)用者了。
除了刪除或者重新提交任務(wù),一般來說任務(wù)號(hào)是不能改變的。即使當(dāng)數(shù)據(jù)庫被導(dǎo)出或者被導(dǎo)入這樣極端的情況,任務(wù)號(hào)也將被保留下來。所以在執(zhí)行含有任務(wù)的數(shù)據(jù)的導(dǎo)入/導(dǎo)出操作時(shí)很可能會(huì)發(fā)生任務(wù)號(hào)沖突的現(xiàn)象。
2、what
what參數(shù)是一個(gè)可以轉(zhuǎn)化為合法PL/SQL調(diào)用的字符串,該調(diào)用將被任務(wù)隊(duì)列自動(dòng)執(zhí)行。在what參數(shù)中,如果使用文字字符串,則該字符串必須用單引號(hào)括起來。 what參數(shù)也可以使用包含我們所需要字符串值的VARCHAR2變量。實(shí)際的PL/SQL調(diào)用必須用分號(hào)隔開。在PL/SQL調(diào)用中如果要嵌入文字字符串,則必須使用兩個(gè)單引號(hào)。
what參數(shù)的長(zhǎng)度在Oracle7.3中限制在2000個(gè)字節(jié)以內(nèi),在Oracle 8.0以后,擴(kuò)大到了4000個(gè)字節(jié),這對(duì)于一般的應(yīng)用已完全足夠。該參數(shù)的值一般情況下都是對(duì)一個(gè)PL/SQL存儲(chǔ)過程的調(diào)用。在實(shí)際應(yīng)用中,盡管可以使用大匿名Pl/SQL塊,但建議大家最好不要這樣使用。還有一個(gè)實(shí)際經(jīng)驗(yàn)就是最好將存儲(chǔ)過程調(diào)用封裝在一個(gè)匿名塊中,這樣可以避免一些比較莫名錯(cuò)誤的產(chǎn)生。我來舉一個(gè)例子,一般情況下,what參數(shù)可以這樣引用:
what =>’my_procedure(parameter1);’ |
但是比較安全的引用,應(yīng)該這樣寫:
what =>’begin my_procedure(parameter1); end;’ |
任何時(shí)候,我們只要通過更改what參數(shù)就可以達(dá)到更改任務(wù)定義的目的。但是有一點(diǎn)需要注意,通過改變what參數(shù)來改變?nèi)蝿?wù)定義時(shí),用戶當(dāng)前的會(huì)話設(shè)置也被記錄下來并成為任務(wù)運(yùn)行環(huán)境的一部分。如果當(dāng)前會(huì)話設(shè)置和最初提交任務(wù)時(shí)的會(huì)話設(shè)置不同,就有可能改變?nèi)蝿?wù)的運(yùn)行行為。意識(shí)到這個(gè)潛在的副作用是非常重要的,無論何時(shí)只要應(yīng)用到任何DBMS_JOB過程中的what參數(shù)時(shí)就一定要確保會(huì)話設(shè)置的正確。
3、next_date
Next_date參數(shù)是用來調(diào)度任務(wù)隊(duì)列中該任務(wù)下一次運(yùn)行的時(shí)間。這個(gè)參數(shù)對(duì)于DBMS_JOB.SUBMIT和DBMS_JOB.BROKEN這兩個(gè)過程確省為系統(tǒng)當(dāng)前時(shí)間,也就是說任務(wù)將立即運(yùn)行。
當(dāng)將一個(gè)任務(wù)的next_date參數(shù)賦值為null時(shí),則該任務(wù)下一次運(yùn)行的時(shí)間將被指定為4000年1月1日,也就是說該任務(wù)將永遠(yuǎn)不再運(yùn)行。在大多數(shù)情況下,這可能是我們不愿意看到的情形。但是,換一個(gè)角度來考慮,如果想在任務(wù)隊(duì)列中保留該任務(wù)而又不想讓其運(yùn)行,將next_date設(shè)置為null卻是一個(gè)非常簡(jiǎn)單的辦法。
Next_date也可以設(shè)置為過去的一個(gè)時(shí)間。這里要注意,系統(tǒng)任務(wù)的執(zhí)行順序是根據(jù)它們下一次的執(zhí)行時(shí)間來確定的,于是將next_date參數(shù)設(shè)置回去就可以達(dá)到將該任務(wù)排在任務(wù)隊(duì)列前面的目的。這在任務(wù)隊(duì)列進(jìn)程不能跟上將要執(zhí)行的任務(wù)并且一個(gè)特定的任務(wù)需要盡快執(zhí)行時(shí)是非常有用的。
4、Interval
Internal參數(shù)是一個(gè)表示Oracle合法日期表達(dá)式的字符串。這個(gè)日期字符串的值在每次任務(wù)被執(zhí)行時(shí)算出,算出的日期表達(dá)式有兩種可能,要么是未來的一個(gè)時(shí)間要么就是null。這里要強(qiáng)調(diào)一點(diǎn):很多開發(fā)者都沒有意識(shí)到next_date是在一個(gè)任務(wù)開始時(shí)算出的,而不是在任務(wù)成功完成時(shí)算出的。
當(dāng)任務(wù)成功完成時(shí),系統(tǒng)通過更新任務(wù)隊(duì)列目錄表將前面算出的next_date值置為下一次任務(wù)要運(yùn)行的時(shí)間。當(dāng)由interval表達(dá)式算出next_date是null時(shí),任務(wù)自動(dòng)從任務(wù)隊(duì)列中移出,不會(huì)再繼續(xù)執(zhí)行。因此,如果傳遞一個(gè)null值給interval參數(shù),則該任務(wù)僅僅執(zhí)行一次。
通過給interval參數(shù)賦各種不同的值,可以設(shè)計(jì)出復(fù)雜運(yùn)行時(shí)間計(jì)劃的任務(wù)。本文后面的“任務(wù)間隔和日期算法”將對(duì)interval表達(dá)式進(jìn)行詳細(xì)討論,并給出一個(gè)實(shí)際有用interval表達(dá)式的例子。
四、任務(wù)隊(duì)列架構(gòu)和運(yùn)行環(huán)境
任務(wù)隊(duì)列在Oracle系統(tǒng)中其實(shí)是一個(gè)子系統(tǒng),它具有自己特定的后臺(tái)過程和目錄表。該子系統(tǒng)設(shè)計(jì)的目的是為了能不在用戶干預(yù)下自動(dòng)運(yùn)行PL/SQL過程。
1、任務(wù)隊(duì)列后臺(tái)過程
任務(wù)隊(duì)列(SNP)后臺(tái)過程隨著Oracle實(shí)例的啟動(dòng)而同時(shí)啟動(dòng)。在文章前面已經(jīng)談到初始化文件init.ora中的參數(shù)JOB_QUEUE_PROCESSES,用來設(shè)置有幾個(gè)隊(duì)列過程。這里設(shè)置了幾個(gè)過程,系統(tǒng)中就會(huì)有幾個(gè)SNP過程被啟動(dòng)。JOB_QUEUE_PROCESSES這個(gè)參數(shù),可以是0到36中的任何一個(gè)數(shù),也就是說對(duì)于每個(gè)Oracle實(shí)例最多可以有36個(gè)SNP過程,也可以不支持隊(duì)列過程(=0)。在大多數(shù)操作系統(tǒng)中,SNP三個(gè)字母常作為過程名的一部分出現(xiàn)。如,在unix系統(tǒng)中,如果該Oracle實(shí)例名為ora8,有三個(gè)任務(wù)隊(duì)列過程,則這三個(gè)任務(wù)隊(duì)列過程名稱為:
ora_ora8_snp0 ora_ora8_snp1 ora_ora8_snp2 |
SNP后臺(tái)過程和其他的Oracle后臺(tái)過程的一個(gè)重要區(qū)別就是殺掉一個(gè)SNP過程不會(huì)影響到Oracle實(shí)例。當(dāng)一個(gè)任務(wù)隊(duì)列過程失控或者消耗太多的資源時(shí),就可以將其殺掉,當(dāng)然這種情況不是經(jīng)常遇到的。當(dāng)一個(gè)SNP過程被殺掉或者失敗時(shí),Oracle就自動(dòng)啟動(dòng)一個(gè)新的SNP過程來代替它。
2、有關(guān)任務(wù)隊(duì)列的初始化參數(shù)
初始化文件init.ora中的幾個(gè)參數(shù)控制著任務(wù)隊(duì)列后臺(tái)的運(yùn)行,下面我們將對(duì)其進(jìn)行詳細(xì)討論。
(1)、JOB_QUEUE_INTERVAL
任務(wù)隊(duì)列過程定期喚醒并檢查任務(wù)隊(duì)列目錄表是否有任務(wù)需要執(zhí)行。參數(shù)JOB_QUEUE_INTERVAL決定SNP過程兩次檢查目錄表之間“休眠”多長(zhǎng)時(shí)間(單位為秒)。間隔設(shè)的太小會(huì)造成由于SNP過程不斷檢查目錄表而導(dǎo)致不必要的系統(tǒng)吞吐量。相反如果間隔設(shè)得太大,SNP過程在特定的時(shí)間沒有被喚醒,那個(gè)時(shí)間的任務(wù)就不會(huì)能被運(yùn)行。最佳的時(shí)間間隔設(shè)置要綜合考慮系統(tǒng)環(huán)境中不同的任務(wù),60秒的確省設(shè)置可以滿足大多數(shù)的應(yīng)用。
(2)、JOB_QUEUE_KEEP_CONNECTIONS
除了前面介紹的JOB_QUEUE_PROCESS和JOB_QUEUE_INTERVAL兩個(gè)參數(shù)以外,影響SNP后臺(tái)過程行為的第三個(gè)參數(shù)是JOB_QUEUE_KEEP_CONNECTIONS。當(dāng)該參數(shù)為TRUE時(shí),SNP過程在兩個(gè)任務(wù)的運(yùn)行期間(也就是休眠期間),仍然和Oracle保持開放的連接。相反,如果為FALSE時(shí),SNP過程將和數(shù)據(jù)庫斷開連接,當(dāng)喚醒時(shí)刻到來時(shí)又重新連接并檢查任務(wù)隊(duì)列。
選擇這兩種方法中的那一種,主要是考慮任務(wù)隊(duì)列的有效性和數(shù)據(jù)庫關(guān)閉方法。長(zhǎng)期保持連接的效率比較高,但任務(wù)隊(duì)列會(huì)受到正常關(guān)閉數(shù)據(jù)庫的影響。這是因?yàn)槿蝿?wù)隊(duì)列過程對(duì)于服務(wù)器管理器看來和一個(gè)普通用戶的過程沒有什么不同,而正常的關(guān)閉數(shù)據(jù)庫需要讓所有的用戶都斷開連接。而斷開連接和重新連接又給數(shù)據(jù)庫增加了負(fù)荷,但是可定期地使數(shù)據(jù)庫沒有可連接SNP過程,也就可以使數(shù)據(jù)庫正常關(guān)閉。對(duì)于有很多任務(wù)或者是任務(wù)重復(fù)執(zhí)行的時(shí)間間隔較短(一個(gè)小時(shí)或者更少)的環(huán)境,一般將JOB_QUEUE_KEEP_CONNECTIOONS設(shè)置為TRUE,并修改關(guān)閉數(shù)據(jù)庫的腳本為立即關(guān)閉。對(duì)于嚴(yán)格要求采用正常方式關(guān)閉的數(shù)據(jù)庫或者是任務(wù)較少,重復(fù)間隔較長(zhǎng)的環(huán)境,一般將該參數(shù)設(shè)置為FALSE。最好,要提醒一句,SNP過程僅在沒有任何任務(wù)運(yùn)行時(shí)才斷開,這種情況下,那些需要比較長(zhǎng)時(shí)間運(yùn)行的任務(wù)SNP將在它們的生命周期內(nèi)一致保持開放的連接,這就延遲了正常關(guān)閉數(shù)據(jù)庫的時(shí)間。
3、建立運(yùn)行環(huán)境
當(dāng)SNP過程喚醒時(shí),它首先查看任務(wù)隊(duì)列目錄中所有的任務(wù)是否當(dāng)前的時(shí)間超過了下一次運(yùn)行的日期時(shí)間。SNP檢測(cè)到需要該時(shí)間立即執(zhí)行的任務(wù)后,這些任務(wù)按照下一次執(zhí)行日期的順序依次執(zhí)行。當(dāng)SNP過程開始執(zhí)行一個(gè)任務(wù)時(shí),其過程如下:
- 以任務(wù)所有者的用戶名開始一個(gè)新的數(shù)據(jù)庫會(huì)話。
- 當(dāng)任務(wù)第一次提交或是最后一次被修改時(shí),更改會(huì)話NLS設(shè)置和目前就緒的任務(wù)相匹配。
- 通過interval日期表達(dá)式和系統(tǒng)時(shí)間,計(jì)算下一次執(zhí)行時(shí)間。
- 執(zhí)行任務(wù)定義的PL/SQL
- 如果運(yùn)行成功,任務(wù)的下一次執(zhí)行日期(next_date)被更新,否則,失敗計(jì)數(shù)加1。
- 經(jīng)過JOB_QUEUS_INTERVAL秒后,又到了另一個(gè)任務(wù)的運(yùn)行時(shí)間,重復(fù)上面的過程。
在前兩步中,SNP過程創(chuàng)建了一個(gè)模仿用戶運(yùn)行任務(wù)定義的PL/SQL的會(huì)話環(huán)境。然而,這個(gè)模仿的運(yùn)行環(huán)境并不是和用戶實(shí)際會(huì)話環(huán)境完全一樣,需要注意以下兩點(diǎn):第一,在任務(wù)提交時(shí)任何可用的非確省角色都將在任務(wù)運(yùn)行環(huán)境中不可用。因此,那些想從非確省角色中取得權(quán)限的任務(wù)不能提交,用戶確省角色的修改可以通過在任務(wù)未來運(yùn)行期間動(dòng)態(tài)修改來完成。第二,任何任務(wù)定義本身或者過程執(zhí)行中需要的數(shù)據(jù)庫聯(lián)接都必須完全滿足遠(yuǎn)程的用戶名和密碼。SNP過程不能在沒有顯式指明口令的情況下初始化一個(gè)遠(yuǎn)程會(huì)話。顯然,SNP過程不能假定將本地用戶的口令作為遠(yuǎn)程運(yùn)行環(huán)境會(huì)話設(shè)置的一部分。
提交的任務(wù)如果運(yùn)行失敗會(huì)怎么樣呢?當(dāng)任務(wù)運(yùn)行失敗時(shí),SNP過程在1分鐘后將再次試圖運(yùn)行該任務(wù)。如果這次運(yùn)行又失敗了,下一次嘗試將在2分鐘后進(jìn)行,再下一次在4分鐘以后。任務(wù)隊(duì)列每次加倍重試間隔直到它超過了正常的運(yùn)行間隔。在連續(xù)16次失敗后,任務(wù)就被標(biāo)記為中斷的(broken),如果沒有用戶干預(yù),任務(wù)隊(duì)列將不再重復(fù)執(zhí)行。
五、任務(wù)隊(duì)列字典表和視圖
任務(wù)隊(duì)列中的任務(wù)信息可以通過表3所示的幾個(gè)字典視圖來查看,這些視圖是由CATJOBQ.sql腳本創(chuàng)建的。表4和5是各個(gè)視圖每個(gè)字段的含義。
表3. 任務(wù)隊(duì)列中關(guān)于任務(wù)的數(shù)據(jù)字典視圖
視圖名 | 描述 |
DBA_JOBS | 本數(shù)據(jù)庫中定義到任務(wù)隊(duì)列中的任務(wù) |
DBA_JOBS_RUNNING | 目前正在運(yùn)行的任務(wù) |
USER_JOBS | 當(dāng)前用戶擁有的任務(wù) |
表4. DBA_JOBS 和 USER_JOBS.字典視圖的字段含義
字段(列) | 類型 | 描述 |
JOB | NUMBER | 任務(wù)的唯一標(biāo)示號(hào) |
LOG_USER | VARCHAR2(30) | 提交任務(wù)的用戶 |
PRIV_USER | VARCHAR2(30) | 賦予任務(wù)權(quán)限的用戶 |
SCHEMA_USER | VARCHAR2(30) | 對(duì)任務(wù)作語法分析的用戶模式 |
LAST_DATE | DATE | 最后一次成功運(yùn)行任務(wù)的時(shí)間 |
LAST_SEC | VARCHAR2(8) | 如HH24:MM:SS格式的last_date日期的小時(shí),分鐘和秒 |
THIS_DATE | DATE | 正在運(yùn)行任務(wù)的開始時(shí)間,如果沒有運(yùn)行任務(wù)則為null |
THIS_SEC | VARCHAR2(8) | 如HH24:MM:SS格式的this_date日期的小時(shí),分鐘和秒 |
NEXT_DATE | DATE | 下一次定時(shí)運(yùn)行任務(wù)的時(shí)間 |
NEXT_SEC | VARCHAR2(8) | 如HH24:MM:SS格式的next_date日期的小時(shí),分鐘和秒 |
TOTAL_TIME | NUMBER | 該任務(wù)運(yùn)行所需要的總時(shí)間,單位為秒 |
BROKEN | VARCHAR2(1) | 標(biāo)志參數(shù),Y標(biāo)示任務(wù)中斷,以后不會(huì)運(yùn)行 |
INTERVAL | VARCHAR2(200) | 用于計(jì)算下一運(yùn)行時(shí)間的表達(dá)式 |
FAILURES | NUMBER | 任務(wù)運(yùn)行連續(xù)沒有成功的次數(shù) |
WHAT | VARCHAR2(2000) | 執(zhí)行任務(wù)的PL/SQL塊 |
CURRENT_SESSION_LABEL | RAW MLSLABEL | 該任務(wù)的信任Oracle會(huì)話符 |
CLEARANCE_HI | RAW MLSLABEL | 該任務(wù)可信任的Oracle最大間隙 |
CLEARANCE_LO | RAW MLSLABEL | 該任務(wù)可信任的Oracle最小間隙 |
NLS_ENV | VARCHAR2(2000) | 任務(wù)運(yùn)行的NLS會(huì)話設(shè)置 |
MISC_ENV | RAW(32) | 任務(wù)運(yùn)行的其他一些會(huì)話參數(shù) |
表 5. 視圖DBA_JOBS_RUNNING的字段含義
列 | 數(shù)據(jù)類型 | 描述 |
SID | NUMBER | 目前正在運(yùn)行任務(wù)的會(huì)話ID |
JOB | NUMBER | 任務(wù)的唯一標(biāo)示符 |
FAILURES | NUMBER | 連續(xù)不成功執(zhí)行的累計(jì)次數(shù) |
LAST_DATE | DATE | 最后一次成功執(zhí)行的日期 |
LAST_SEC | VARCHAR2(8) | 如HH24:MM:SS格式的last_date日期的小時(shí),分鐘和秒 |
THIS_DATE | DATE | 目前正在運(yùn)行任務(wù)的開始日期 |
THIS_SEC | VARCHAR2(8) | 如HH24:MM:SS格式的this_date日期的小時(shí),分鐘和秒 |
六、任務(wù)重復(fù)運(yùn)行間隔和間隔設(shè)計(jì)算法
任務(wù)重復(fù)運(yùn)行的時(shí)間間隔取決于interval參數(shù)中設(shè)置的日期表達(dá)式。下面就來詳細(xì)談?wù)勗撊绾卧O(shè)置interval參數(shù)才能準(zhǔn)確滿足我們的任務(wù)需求。一般來講,對(duì)于一個(gè)任務(wù)的定時(shí)執(zhí)行,有三種定時(shí)要求。
- 在一個(gè)特定的時(shí)間間隔后,重復(fù)運(yùn)行該任務(wù)。
- 在特定的日期和時(shí)間運(yùn)行任務(wù)。
- 任務(wù)成功完成后,下一次執(zhí)行應(yīng)該在一個(gè)特定的時(shí)間間隔之后。
第一種調(diào)度任務(wù)需求的日期算法比較簡(jiǎn)單,即'SYSDATE+n',這里n是一個(gè)以天為單位的時(shí)間間隔。表6給出了一些這種時(shí)間間隔設(shè)置的例子。
表6 一些簡(jiǎn)單的interval參數(shù)設(shè)置例子
描述 | Interval參數(shù)值 |
每天運(yùn)行一次 | 'SYSDATE + 1' |
每小時(shí)運(yùn)行一次 | 'SYSDATE + 1/24' |
每10分鐘運(yùn)行一次 | 'SYSDATE + 10/(60*24)' |
每30秒運(yùn)行一次 | 'SYSDATE + 30/(60*24*60)' |
每隔一星期運(yùn)行一次 | 'SYSDATE + 7' |
不再運(yùn)行該任務(wù)并刪除它 | NULL |
表6所示的任務(wù)間隔表達(dá)式不能保證任務(wù)的下一次運(yùn)行時(shí)間在一個(gè)特定的日期或者時(shí)間,僅僅能夠指定一個(gè)任務(wù)兩次運(yùn)行之間的時(shí)間間隔。例如,如果一個(gè)任務(wù)第一次運(yùn)行是在凌晨12點(diǎn),interval指定為'SYSDATE + 1',則該任務(wù)將被計(jì)劃在第二天的凌晨12點(diǎn)執(zhí)行。但是,如果某用戶在下午4點(diǎn)手工(DBMS_JOB.RUN)執(zhí)行了該任務(wù),那么該任務(wù)將被重新定時(shí)到第二天的下午4點(diǎn)。還有一個(gè)可能的原因是如果數(shù)據(jù)庫關(guān)閉或者說任務(wù)隊(duì)列非常的忙以至于任務(wù)不能在計(jì)劃的那個(gè)時(shí)間點(diǎn)準(zhǔn)時(shí)執(zhí)行。在這種情況下,任務(wù)將試圖盡快運(yùn)行,也就是說只要數(shù)據(jù)庫一打開或者是任務(wù)隊(duì)列不忙就開始執(zhí)行,但是這時(shí),運(yùn)行時(shí)間已經(jīng)從原來的提交時(shí)間漂移到了后來真正的運(yùn)行時(shí)間。這種下一次運(yùn)行時(shí)間的不斷“漂移”是采用簡(jiǎn)單時(shí)間間隔表達(dá)式的典型特征。
第二種調(diào)度任務(wù)需求相對(duì)于第一種就需要更復(fù)雜的時(shí)間間隔(interval)表達(dá)式,表7是一些要求在特定的時(shí)間運(yùn)行任務(wù)的interval設(shè)置例子。
表 7. 定時(shí)到特定日期或時(shí)間的任務(wù)例子
描述 | INTERVAL參數(shù)值 |
每天午夜12點(diǎn) | 'TRUNC(SYSDATE + 1)' |
每天早上8點(diǎn)30分 | 'TRUNC(SYSDATE + 1) + (8*60+30)/(24*60)' |
每星期二中午12點(diǎn) | 'NEXT_DAY(TRUNC(SYSDATE ), ''TUESDAY'' ) + 12/24' |
每個(gè)月第一天的午夜12點(diǎn) | 'TRUNC(LAST_DAY(SYSDATE ) + 1)' |
每個(gè)季度最后一天的晚上11點(diǎn) | 'TRUNC(ADD_MONTHS(SYSDATE + 2/24, 3 ), 'Q' ) -1/24' |
每星期六和日早上6點(diǎn)10分 | 'TRUNC(LEAST(NEXT_DAY(SYSDATE, ''SATURDAY"), NEXT_DAY(SYSDATE, "SUNDAY"))) + (6×60+10)/(24×60)' |
第三種調(diào)度任務(wù)需求無論通過怎樣設(shè)置interval日期表達(dá)式也不能滿足要求。這時(shí)因?yàn)橐粋€(gè)任務(wù)的下一次運(yùn)行時(shí)間在任務(wù)開始時(shí)才計(jì)算,而在此時(shí)是不知道任務(wù)在何時(shí)結(jié)束的。遇到這種情況怎么辦呢?當(dāng)然辦法肯定是有的,我們可以通過為任務(wù)隊(duì)列寫過程的辦法來實(shí)現(xiàn)。這里我只是簡(jiǎn)單介紹以下,可以在前一個(gè)任務(wù)隊(duì)列執(zhí)行的過程中,取得任務(wù)完成的系統(tǒng)時(shí)間,然后加上指定的時(shí)間間隔,拿這個(gè)時(shí)間來控制下一個(gè)要執(zhí)行的任務(wù)。這里有一個(gè)前提條件,就是目前運(yùn)行的任務(wù)本身必須要嚴(yán)格遵守自己的時(shí)間計(jì)劃。
結(jié)論
Oracle中的定時(shí)任務(wù)是在Oracle系統(tǒng)中是一個(gè)非常重要的子系統(tǒng),運(yùn)用得當(dāng),可以極大的提高我們的系統(tǒng)運(yùn)行和維護(hù)能力。而Oracle數(shù)據(jù)復(fù)制的延遲事務(wù)隊(duì)列管理完全是基于Oracle的隊(duì)列任務(wù),對(duì)其的深刻理解有助于我們更好地管理數(shù)據(jù)復(fù)制。
posted on 2009-08-26 10:30 鴻雁 閱讀(461) 評(píng)論(0) 編輯 收藏