oracle之三 自動任務調度


Oracle 自動任務調度

13.1 Oracle任務調度概述

在Oracle中任務調度指某一(組)執行程序在特定的時間被周期性的執行。Oracle把任務調度稱為job(作業)。

Advanced Scheduler Concepts:(PPT-II-450)

13.2 理解以下概念:

1) Advanced SCHEDULER下的jobs

JOB翻譯為作業,一個基本的JOB由兩方面組成:program和schedule。JOB總體上可分為兩大類,基於時間的JOB和基於事件的JOB。
在Oracle 10g之前,采用dbms_job程序包來完成任務調度的相關工作。在Oracle 10g之后,Oracle推出了功能更加強大的
dbms_scheduler來完成作業調度工作。

*考點:必須將JOB_QUEUE_PROCESSES 實例參數設置為>0的值,否則調度程序將無法運行,默認值為1000。如果有任何定義的、
活動的作業,那么總是運行作業隊列協調器(后台進程cjq0)。

SQL> show parameter job_queue_processes

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
job_queue_processes integer 1000

SQL> select program from v$process where program like '%J%';

PROGRAM
------------------------------------------------
oracle@timran.localdomain (J000) //術語:job slave即job工作者,根據參數可以有1000個
oracle@timran.localdomain (CJQ0) //術語:Job Coordinator即job協調員

2) Advanced SCHEDULER下的program

Program指的是運行的程序。包括具體的要操作的執行代碼,可選的是三種類型:

PL/SQL BLOCK : 標准的pl/sql代碼塊;
STORED PROCEDURE : 編譯好的PL/SQL存儲過程,或者Java存儲過程,以及外部的c子程序;
EXECUTEABLE : ORACLE數據庫之外的應用,比如操作系統命令等等。

3) Advanced SCHEDULER下的schedule

Scheduler有的資料翻譯為調度,有的翻譯成時間表,簡單來說指的就是作業運行周期,即時間和頻率。

總結一下:如果不考慮與資源計划的結合,Schedules(調度);Programs(程序);Jobs(任務)這三者之間到底是個什么關系?直白地來說
就是:program負責具體做什么(左膀),schedule負責什么時候做(右臂),job就簡單了(聯手左膀右臂)。11g的SCHEDULER提供了六種
建立Job的存儲過程,可以將program、schedule、job分立創建,也可以混合創建,相互組合非常靈活。

瀏覽一下dbms_scheduler中的內容。

SQL> spool /tmp/sch.txt
SQL> desc dbms_scheduler
SQL> spool off
$more /tem/sch.txt

4)JOB CLASSES

相當於創建了一個job組,可以將那些具有相同特性的job,統統放到一個Job Classes中,在Job Classes中的Jobs可以指派優先級(1-5),
,默認優先級是3,而1的優先級最高,然后讓Job Classes與資源計划器結合進行管理。

5)WINDOW

窗口指定了作業運行的起始時間(START DATE)、終止時間(END DATE),運行時間(DURATION),以及重復間隔(REPEAT INTERVAL)等,
它實際上擴展了SCHEDULER(時間表)的概念,所謂擴展是指窗口可以激活資源管理計划,當窗口打開時,數據庫自動切換到相關的
resource plan上,此時這個resource plan便處於活動狀態(ACTIVE)。

窗口對於job class也有着特殊的意義,通過job class和resource plan聯系,這就使窗口下被激活的resource plan中所關聯的job class中
的所有job被激活了,這些job會根據優先權調度運行。

6)JOB CHAIN

CHAIN可以被視做一組Programs的組合,舉個簡單的例子:運行PROGRAM:A以及PROGRAM:B,如果成功的話繼續運行PROGRAM:C,
否則的話運行PROGRAM:D。Programs:A、B、C、D以及執行的邏輯關系就構成了一個最簡單的CHAIN。

7)輕型作業

輕型作業不顯示在DBA_SCHEDULER_JOBS視圖中,因為輕型作業不是模式對象,與普通作業相比創建和刪除輕型作業的開銷非常小。
使用輕型作業有兩種情形:1)作業成百上千次的批量執行,2)單個作業運行時間較短。

DBMS_SCHEDULER程序包可以使用最少的語法來創建輕量作業。輕量作業只有很少的參數可以指定:作業參數和計划。作業的其余
元數據(包括權限)都是從作業模板繼承來的。輕量作業的模板必須是PL/SQL 塊或存儲過程。輕量作業必須使用DBMS_SCHEDULER
程序包在PL/SQL 中創建。JOB_STYLE參數在EM 中是不可見的。

例1,指定時間和頻率的
dbms_scheduler.create_job(
job_name =>'test_ltwtjob1',
program_name =>'test_prog',
repeat_interval =>'freq=hourly',
end_date =>to_timestamp(sysdate+1),
job_style =>'lightweight',

例2,使用預定義計划
dbms_scheduler.create_job(
job_name =>'test_ltwtjob1',
program_name =>'test_prog',
shedule_name =>'test_sched'
job_style =>'lightweight',


以上兩種方法,輕型作業的名字叫TEST_LTWTJOB1,程序test_prog就是它的模板,(這個模板就是指program_name是一個單獨的模塊),
job_style是輕型作業的關鍵字。

建立單一的輕型作業也許意義不大,另一種方法是通過PL/SQL塊一次執行幾百個輕量級作業的數組。

考點:輕型作業的指定的程序類型只能是PLSQL_BLOCK或者STORED_PROCEDURE。

8)基於事件(Event)的作業

SCHEDULER中有兩種觸發EVENT的情況:

Scheduler觸發的Events

Scheduler 中觸發的Events,一般是說當前schduler 中job 的狀態發生修改,類似job 啟動,或者運行結束,或者達到運行時間
等諸如此類的動作,都能夠拋出一個EVENT,接收到EVENT 的application 就可以根據這些信息進行適當的處理。

Application觸發的Events

外部的應用也可以觸發Events,並且由Scheduler來接收並處理這一類型的Events。所謂Scheduler 處理EVENT 就是指Scheduler
啟動相應的job來執行相關操作,這類job在創建時專門聲明了event 的處理,這樣當接收到EVENT 時,這類job就會啟動。

建立和管理基於事件(Event)的作業的方法超出了OCP考試范疇,這里就不多說了。

13.3 例:

下面通過實例來演示,如何創建program、schedule、job,以便能初步理解三者間的關系。

我們使用分立創建三者的方法,先建一個測試表

SQL> create table scott.job_test1(my_date date);

第一步,創建一個名叫my_pro1的program,(帶PL/SQL BLOCK)操作如下:

BEGIN
DBMS_SCHEDULER.CREATE_PROGRAM(
program_name =>'my_pro1',
program_action =>'begin
insert into scott.job_test1 values(sysdate);
commit;
end;',
program_type =>'PLSQL_BLOCK',
number_of_arguments =>0,
comments =>'insert sysdate into table',
enabled =>TRUE);
END;
/

PL/SQL procedure successfully completed.
  
通過上述語句,我們定義了一個program,類型是一個oracle匿名塊,其動作是將輸入sysdate插入到scott.job_test中。

前三個屬性是不可以省略的,它們沒有缺省值,必須指定,屬性number_of_arguments是指定支持的參數個數,默認為0,
最多255,這里又置為0,強調此參數為0,因為program_type是PLSQL_BLOCK。要為progremm 添加參數需要使用
DEFINE_PROGRAM_ARGUMENT存儲過程。

第二步:我們建立一個schedule,規定開始program的操作時間,及操作頻率。這里定義了20秒執行一次。

BEGIN
dbms_scheduler.create_schedule(
repeat_interval => 'FREQ=SECONDLY;INTERVAL=20',
start_date => sysdate,
comments => 'Start Every 20 seconds',
schedule_name => 'my_sch1');
END;
/

此處REPEAT_INTERVAL參數的語法結構比較復雜。其中最重要的是FREQ和INTERVAL 兩個關鍵字。

FREQ 關鍵字用來指定間隔的時間周期,可選參數有:YEARLY, MONTHLY, WEEKLY, DAILY, HOURLY, MINUTELY, and SECONDLY,
分別表示年、月、周、日、時、分、秒等單位。

INTERVAL 關鍵字用來指定間隔的頻繁,可指定的值的范圍從1-99。

本例'FREQ=SECONDLY;INTERVAL=30表示每30秒鍾執行一次,如果是'FREQ=DAILY;INTERVAL=1';就表示每天執行一次,


第三步:創建job,按照指定的schedule,執行program,創建job時,start_date,repeat_interval,job_action等均無須指定,因為這些參數
將由program和schedule來控制。操作如下:

BEGIN
dbms_scheduler.create_job(
job_name => 'my_job1',
program_name => 'my_pro1',
schedule_name => 'my_sch1',
comments => 'insert sysdate into table',
enabled => TRUE);
END;
/

這樣,操作完成后,ORACLE就會自動定時(當前設置為30秒執行一次)program中定義的操作。

檢查結果:

SQL> select * from scott.job_test1;

MY_DATE
-------------------
2012-11-22 15:56:13
2012-11-22 15:56:43
2012-11-22 15:57:13
......

可以通過一些視圖查看JOB狀態

DBA_SCHEDULER_JOBS
DBA_SCHEDULER_RUNNING_JOBS; //這兩個都是查看當前job運行狀態的(考點)
DBA_SCHEDULER_JOB_LOG
DBA_SCHEDULER_JOB_RUN_DETAILS

例如,查看剛剛創建的"MY_JOB1"任務的執行情況的細節,執行命令如下:

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

除了作業按照時間表自動運行,你也可以手工干預它們,舉幾個例子:

使能作業:
SQL> exec dbms_scheduler.enable('my_job1');
禁用作業:
SQL> exec dbms_scheduler.disable('my_job1');
刪除作業:
SQL> exec dbms_scheduler.drop_job('my_job1');
運行作業:
SQL> exec dbms_scheduler.run_job('my_job1');
停止作業:
SQL> exec dbms_scheduler.stop_job('my_job1');

等等,很多類似的存儲過程...

從管理角度看,你能創建JOB,也應該能修改JOB,即修改JOB的屬性,由於JOB屬性眾多,Oracle把這部分工作獨立出來作為一個
存儲過程,這就是DBMS_SCHEDULER.set_attribute, 此過程可以修改JOB屬性,這里僅舉幾個(也是考點):

1)JOB_TYPE:指定job執行的任務的類型

有四個可選值:'PLSQL_BLOCK', 'STORED_PROCEDURE', 'EXECUTABLE', and 'CHAIN'。

2)JOB_ACTION:指定job 執行的任務.這一參數所指定的值依賴於JOB_TYPE 參數中的值, 比如說JOB_TYPE設置為 'STORED_PROCEDURE',
那么本參數值中指定的可以是ORACLE 中的過程名。

3)LOGGING_LEVEL:指定對jobs 執行情況記錄的日志信息級別。

SCHEDULER 管理的JOB 對任務的執行情況專門進行了記錄,同時用戶還可以選擇日志中記錄信息的級別,有下列三種選擇:

DBMS_SCHEDULER.LOGGING_OFF:關閉日志記錄功能;
DBMS_SCHEDULER.LOGGING_RUNS:對任務的運行信息進行記錄;
DBMS_SCHEDULER.LOGGING_FULL:記錄任務所有相關信息,不僅有任務的運行情況,甚至連任務的創建、修改等也均將記入日志。

4)AUTO_DROP:當為TRUE時,一旦job到達停止運行的時間,該job就會被自動刪除,否則的話job仍然存在,不過狀態被修改為COMPLETED。

5)RESTARTABLE:指定jobs運行出錯后,能否適時重啟,該參數默認情況下設置為FALSE,如果設置為TRUE,就表示當任務運行時出錯,
下次運行時間點到達時仍會啟動,並且如果運行仍然出錯,會再重復,連接出錯達到6次,該job 就會停止。

13.5 Job Class(類)和 Window(窗口)

job class包含着一組有相同特性的job, 而window是一個時間段,當系統時間進入到窗口時間段,則窗口打開,作業運行。

它們和資源計划的關聯是個難點:一個job是怎樣和資源計划聯系起來的?

看圖(PPT-II-452),通過兩條線路將JOB和資源計划關聯起來的,需要理解的是:

第一條線路:
創建一個job class,將該Job class綁定某個資源用戶組,則這個Job_Class將服從該用戶組的資源分配計划。

創建job,再通過set_attribute過程賦予相對優先權(1-5), 然后將job加入Job Class后,會根據設定的優先值從1-5順序執行的,1首先被執行,默認是3。

第二條線路:
建立window時必須綁定一個resource plan,當系統時間進入window后,便激活了該resource plan。Window也可以設置優先權(high和low)

window的優先級的作用是:在窗口重疊的情況下如何選擇哪個窗口打開,假定有兩個窗口,設置為同一時間
打開則優先級為high的會打開,如果是同樣的優先級,window時間長的打開,如果優先級相同,window時間長度也相同,
怎么辦?則兩個window都不打開,返還給原來活動的window。

window和schedule功能上相似,但Oracle設計讓window和resource plan綁定,以便可以完成不同的resource plan的自動切換。

查看哪個窗口是活動的以及哪個資源計划與該窗口相關聯,可以使用DBA_SCHEDULER_WINDOWS視圖。

SQL>SELECT window_name,resource_plan,enabled,active FROM DBA_SCHEDULER_WINDOWS;

例;Job Class和Window在Scheduler框架內的作用

接續剛才的例子,把兩條線路完成:

4)使用EM建立一個Job Class,名叫My_Class,將之前的MY_JOB1加入到My_Class(MY_JOB1默認加入的是DEFAULT_JOB_CLASS),再將My_Class關聯OLTP組。

5)建立一個叫DAY_WIN的窗口,該窗口將激活DAYTIME計划

BEGIN
DBMS_SCHEDULER.CREATE_WINDOW(
window_name=>'"DAY_WIN"',
resource_plan=>'DAYTIME',
start_date=>systimestamp at time zone 'Asia/Shanghai',
duration=>numtodsinterval(1, 'minute'),
repeat_interval=>'FREQ=MINUTELY;INTERVAL=2',
end_date=>null,
window_priority=>'HIGH',
comments=>'');
END;
/

這將立即打開DAY_WIN窗口,每隔2分鍾將再次打開該窗口,每次激活DAYTIME計划,duration的含義是打開窗口的持續時間。這里的1分鍾是窗口Active狀態為true可以持續1分鍾。
| 2分鍾 | 2分鍾 |...
窗口再次打開間隔2分鍾 |--------------- |---------------|...
窗口持續打開時間1分鍾 |Active | 關閉 |Active| 關閉 |...

也就是說:當repeat_interval(間隔)>duration(持續時間)才有意義,Oracle不檢查這兩個時間單位的邏輯關系。

至此,一個job關聯一個resource_plan的框架已經搭建起來了,4)和5)兩條線路需要聯動配合,實為關鍵。

6)改一下MY_JOB1的時間表,原來它關聯MY_SCH1這個Schedule,現在讓它關聯DAY_WIN這個window,

即EDIT(MY_JOB1)-->Schedul Type-->Use_Pre_Define_Window-->DAY_WIN

改一下MY_JOB1的JOB CLASS,原來它關聯DEFAULT_JOB_CLASS,現在讓它關聯MY_CLASS

測試一下:

SQL> alter system set resource_manager_plan=''; //關閉資源計划,現在沒有資源計划激活。

SQL> select * from scott.job_test1;

可以看到原來是每半分鍾插入一條記錄,現在是每間隔2分鍾插入一條記錄。

SQL> show parameter resource_manager_plan

resource_manager_plan string SCHEDULER[0x115E7]:DAYTIME //DAYTIME資源計划被DAY_WIN自動激活了(保持1分鍾,2分鍾后再激活)。

OK!到此,整個例子基本完成了。

*考點:
1)當create job過程創建作業時,無法指派優先級,必須在后面使用API的set attribute過程。
2)作業A在其類中的優先級是1,作業B在另一個類的優先級是5,作業B處於resource plan中有更高的優先權的使用者組內,則B先於A被執行。


免責聲明!

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



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