基於事件驅動的Oracle作業排程
對很多系統而言,作業排程Scheduler是不可缺少的部分。大資料量集中批次處理、OLAP資料聚集都需要利用業務空閒時段(如夜間)進行處理。Oracle自身提供了較為可靠的執行作業排程器機制,為我們提供了現成的Scheduler元件。
排程作業有兩種大型別:基於時間(Time-Based)和基於事件(Event-Based)。基於時間的排程作業顧名思義,就是設定特定的時間排程規則。依據時間規則在特定的時間點觸發執行程式碼程式。例如:每天夜間22:00執行資料聚合操作,生成聚合資料。在Oracle中,大部分的作業都是這種型別。比如從10G出現的統計資訊收集作業,就是規定在工作日夜間22:00開始進行的基於時間作業。
基於事件的作業排程則是依據特定的事件場景。比如:在應用程式發生故障的時候,啟動資料清理程式,將中間資料結果還原。這樣的作業,排程時間是不確定的,依據具體的業務和程式場景。而且,基於事件作業執行的過程中,要具有作業的特性,也就是作業執行程式碼執行和觸發作業程式之間是非同步執行關係。
在Oracle中,我們可以方便的時候dbms_scheduler包進行基於時間作業的定義。同樣,我們可以藉助Oracle訊息佇列的特性,來實現Event Based作業型別。
1、 原理和環境準備
為了更好說明問題,筆者選擇Oracle 10R2作為實驗環境,並且構建一個新的使用者schema環境。
SQL> show user;
User is "SYS"
SQL> select * from v$version;
BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod
PL/SQL Release 10.2.0.1.0 - Production
CORE 10.2.0.1.0 Production
TNS for 32-bit Windows: Version 10.2.0.1.0 - Production
NLSRTL Version 10.2.0.1.0 – Production
建立一個新使用者testuser,並授予相應的系統和角色許可權。
SQL> create user testuser identified by testuser ;
User created
SQL> alter user testuser quota unlimited on users;
User altered
SQL> grant connect to testuser;
Grant succeeded
SQL> grant create table to testuser;
Grant succeeded
SQL> grant create sequence to testuser;
Grant succeeded
SQL> grant create type to testuser;
Grant succeeded
SQL> GRANT AQ_ADMINISTRATOR_ROLE TO testuser;
Grant succeeded
SQL> GRANT CREATE JOB TO testuser;
Grant succeeded
只有設定了AQ_ADMINISTRATOR_ROLE角色,才能使用Oracle的Advanced Queue元件功能。
原理上:我們要利用Oracle的Advanced Queue元件的功能。要求在特定的Event發生時,我們需要向佇列中傳入一個標記物件。Scheduler會根據特定的標記物件標識來呼叫特定的作業Job程式碼程式。這樣就實現了基本的Event Based Job。
2、日誌插入作業
我們希望實現一個功能,就是在特定事件發生的時候,會向資料表中插入一條記錄。
首先,我們準備程式碼資料表。
SQL> conn testuser/testuser@ots;
Connected to Oracle Database 10g Enterprise Edition Release 10.2.0.1.0
Connected as testuser
SQL> create sequence seq_test;
Sequence created
SQL> create table test_log (id number not null, comments varchar2(100), created date);
Table created
SQL> alter table test_log add constraint pk_test primary key (id);
Table altered
我們建立了日誌資料表。當觸發事件的時候,直接向該資料表中插入一條記錄。
3、配置排程作業
首先,需要定義一個型別type,用於向AQ中觸發作業。該type相當於事件發生的資訊單元。
SQL> create or replace type t_event_que_payload as object (event_name varchar2(30));
2 /
Type created
建立事件表,用來記錄訊息佇列AQ中訊息資訊。
SQL> exec dbms_aqadm.create_queue_table(queue_table => 'event_queue_table',queue_payload_type => 't_event_que_payload',multiple_consumers => true,comment => 'Test Event Queue');
PL/SQL procedure successfully completed
使用dbms_aqadm方法create_queue_table中,兩個最重要的引數:queue_table是建立訊息表的名稱,queue_payload_type則是規定了佇列中存放物件的type型別。
執行後,的確建立了資料表event_queue_table。
SQL> desc event_queue_table;
Name Type Nullable Default Comments
----------------- ------------------- -------- ------- --------
Q_NAME VARCHAR2(30) Y
MSGID RAW(16)
CORRID VARCHAR2(128) Y
PRIORITY NUMBER Y
(篇幅原因,有省略……)
下面需要建立佇列物件,單獨執行出佇列名稱和佇列資料表名稱。
SQL> exec dbms_aqadm.create_queue(queue_name => 'event_queue',queue_table => 'event_queue_table');
PL/SQL procedure successfully completed
SQL> select name, queue_table, qid, queue_type,user_comment from user_queues;
NAME QUEUE_TABLE QID QUEUE_TYPE USER_COMMENT
------------------------------ ------------------------------ ---------- -------------------- --------------------------------------------------------------------------------
EVENT_QUEUE EVENT_QUEUE_TABLE 111623 NORMAL_QUEUE
AQ$_EVENT_QUEUE_TABLE_E EVENT_QUEUE_TABLE 111622 EXCEPTION_QUEUE exception queue
注意,為了佇列AQ,Oracle要建立出多個資料表,用於進行不同的訊息儲存。同時,處於效能等多方面的考量,很多這樣的資料表是採用IOT(Index-Organized Table)結構的。
SQL> select table_name, tablespace_name, iot_name,iot_type from user_tables;
TABLE_NAME TABLESPACE_NAME IOT_NAME IOT_TYPE
------------------------------ ------------------------------ ------------------------------ ------------
TEST_LOG USERS
EVENT_QUEUE_TABLE USERS
AQ$_EVENT_QUEUE_TABLE_S USERS
SYS_IOT_OVER_111613 USERS AQ$_EVENT_QUEUE_TABLE_G IOT_OVERFLOW
AQ$_EVENT_QUEUE_TABLE_I IOT
AQ$_EVENT_QUEUE_TABLE_G IOT
AQ$_EVENT_QUEUE_TABLE_H IOT
AQ$_EVENT_QUEUE_TABLE_T IOT
8 rows selected
最後,啟動建立出的AQ佇列event_queue。
SQL> EXEC DBMS_AQADM.start_queue (queue_name => 'event_queue');
PL/SQL procedure successfully completed
注意,此時佇列狀態開啟為可用。
SQL> select name, queue_table, qid, queue_type,ENQUEUE_ENABLED, DEQUEUE_ENABLED from user_queues;
NAME QUEUE_TABLE QID QUEUE_TYPE ENQUEUE_ENABLED DEQUEUE_ENABLED
----------------------- ---------------------------------------- --------------- ---------------
EVENT_QUEUE EVENT_QUEUE_TABLE 111623 NORMAL_QUEUE YES YES
AQ$_EVENT_QUEUE_TABLE_E EVENT_QUEUE_TABLE 111622 EXCEPTION_QUEUE NO NO
佇列建立到此結束。下面建立作業,使用dbms_scheduler方法。
SQL> begin
2 dbms_scheduler.create_job(job_name => 'event_based_job',
3 job_type => 'PLSQL_BLOCK',
4 job_action => 'begin
5 insert into test_log values (seq_test.nextval, ''TT'', sysdate);
6 commit;
7 end;
8 ',
9 start_date=>systimestamp,
10 event_condition => 'tab.user_data.event_name = ''test_signal''',
11 queue_spec => 'event_queue',
12 enabled => TRUE);
13 end;
14 /
PL/SQL procedure successfully completed
SQL> select job_name, job_creator from user_scheduler_jobs;
JOB_NAME JOB_CREATOR
------------------------------ ------------------------------
EVENT_BASED_JOB TESTUSER
注意包方法的幾個主要引數。Job_name定義了新增加job的名稱。Job_action定義了當這個Job被觸發的時候,需要執行哪段程式碼。Event_condition規定了排程資料物件值為’test_signal’的時候才會執行這個作業。Queue_spec制定了監視事件的佇列名稱。
4、測試作業情況
我們模擬向佇列中插入事件訊息物件的場景。
SQL> DECLARE
2 l_enqueue_options DBMS_AQ.enqueue_options_t;
3 l_message_properties DBMS_AQ.message_properties_t;
4 l_message_handle RAW(16);
5 l_queue_msg t_event_que_payload;
6 BEGIN
7 l_queue_msg := t_event_que_payload('test_signal'); --建立事件event訊息物件;
8
9 DBMS_AQ.enqueue(queue_name => 'event_queue',
10 enqueue_options => l_enqueue_options,
11 message_properties => l_message_properties,
12 payload => l_queue_msg,
13 msgid => l_message_handle);
14 COMMIT;
15 END;
16 /
PL/SQL procedure successfully completed
在實際使用的時候,只需要向AQ佇列中插入訊息體。Oracle就可以根據訊息的內容呼叫特定的作業。觀察結果:
--作業效果;
SQL> select * from test_log;
ID COMMENTS CREATED
---------- ---------- -----------
1 TT 2012/1/29 1
--作業執行記錄;
SQL> col job_name for a20;
SQL> select log_date, job_name, job_class, status from user_scheduler_job_log;
LOG_DATE JOB_NAME JOB_CLASS STATUS
-------------------- -------------------- ------------------------------ ----------
29-1月 -12 01.43.47. EVENT_BASED_JOB DEFAULT_JOB_CLASS SUCCEEDED
484000 下午 +08:00
5、結論
event_based作業型別,在實際中出現的機率並不是很高。主要是一些資料現場恢復和清理工作。使用Oracle的AQ和排程器機制,我們可以方便的將這種型別作業加以實現。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/17203031/viewspace-715226/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Oracle事件驅動的排程作業Oracle事件
- 基於事件的排程事件
- 基於Mesos的作業雲 Elastic-Job-Cloud 原始碼分析 —— 作業排程(一)ASTCloud原始碼
- oracle排程程式作業dbms_schedulerOracle
- oracle使用DBMS_SCHEDULER排程作業Oracle
- Oracle 排程程式作業( dbms_scheduler )Oracle
- 基於 Redis驅動的 Laravel 事件廣播RedisLaravel事件
- 基於事件驅動的測試框架ETS事件框架
- 基於spring實現事件驅動Spring事件
- Quartz.Net 作業排程後臺管理系統,基於ExtjsquartzJS
- 基於匯流排裝置驅動模型的按鍵讀取驅動程式模型
- 全鏈路營銷|基於事件驅動的流程編排系統 策略中心繫統事件
- 作業排程模擬程式
- Hadoop - Azkaban 作業排程Hadoop
- Android 5.0的排程作業JobSchedulerAndroid
- [譯] 理解 NodeJS 中基於事件驅動的架構NodeJS事件架構
- Hadoop作業排程機制Hadoop
- 關於作業自動排程失敗後自動發郵件給操作員的問題
- 基於事件溯源與CDC的事件驅動微服務架構案例原始碼事件微服務架構原始碼
- 基於 ASK + EB 構建容器事件驅動服務事件
- 關於如何設計一個基於事件驅動架構的思考事件架構
- “訊息驅動、事件驅動、流 ”基礎概念解析事件
- 事件驅動的微服務-事件驅動設計事件微服務
- 【作業系統】--處理器排程作業系統
- 批處理作業排程問題
- 作業系統排程演算法作業系統演算法
- 實現Quartz.NET的HTTP作業排程quartzHTTP
- MYSQL事件排程器MySql事件
- 使用EventNext實現基於事件驅動的業務處理事件
- Reactor: Spring釋出基於JVM的非同步事件驅動框架ReactSpringJVM非同步事件框架
- Oracle排程作業引起的空間驟增問題處理記錄Oracle
- 批處理作業排程-分支界限法
- 作業系統之排程演算法作業系統演算法
- 實驗二 作業模擬排程程式
- Net作業排程(二) -CrystalQuartz遠端管理quartz
- 0512作業系統之程式排程作業系統
- Hadoop作業的三種排程演算法Hadoop演算法
- 基於任務排程的企業級分散式批處理方案分散式