全面學習ORACLE Scheduler特性2

來源:互聯網
上載者:User
四、使用Events

  Event直譯對應的中文解釋是指事件,不過單純講事件畢竟太抽象了,舉個樣本來形容吧。A(對應某個應用程式,或者是ORACLE中的進程)在幹活時突然眉頭一皺說道,不好,前方有情況,這可怎麼辦。這時,只見它認真想了想,過了一會兒臉上一喜說道:有了,俗話說早請示啊晚彙報,出現情況要找領導,趕緊給領導發訊息唄。於是B(也是對應某個應用或ORACLE進程)就收到了一條A發過來的"前方有XX情況"的訊息,這個過程就叫EVENT(含A發訊息以及B接收訊息)。

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

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

比如說,由於系統太過於繁忙,超出job啟動時間後30分鐘,job仍然沒能順利啟動,那麼這個時候,Scheduler就可以拋出一條EVENT給外部的應用,以便外部應用能夠及時通知DBA,進行處理。 application 觸發的Events

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

  Scheduler 使用Oracle進階隊列來拋出以及銷毀Events。當拋出Schduler觸發的Events時,Scheduler將訊息入隊到預設的event隊列,application則通過檢查該隊列來處理Events。當拋出application觸發的Events時,application將訊息入隊到處理job對應的隊列中。

  下面我們也按照這兩個類型來介紹Scheduler中的Events。 4.1 Scheduler拋出的Events

  前面說了,Scheduler拋出的Events一般是指job狀態改變時觸發的,那麼是不是說只要job狀態發生了改變,就會觸發Events,其實並非如此,因為預設情況下,job是不觸發Events的。

  Scheduler 中的job有一個屬性叫raise_events,專門用來設定job觸發Events的條件,該屬性在CREATE_JOB時不能執行,因此預設情況下該屬性不會賦值,自然也就不會觸發EVENT。要設定raise_events屬性,只能是在job建立完成後,通過SET_ATTRIBUTE過程修改job的raise_events屬性。

  例如,修改前面建立的job-,啟用raise_events屬性,執行語句如下:

SQL> BEGIN

  2  DBMS_SCHEDULER.SET_ATTRIBUTE('INSERT_TEST_TBL', 'raise_events',  DBMS_SCHEDULER.JOB_ALL_EVENTS)

  3  END;

  4  / PL/SQL procedure successfully completed.

  上述樣本中指定的raise_events屬性的屬性值DBMS_SCHEDULER.JOB_ALL_EVENTS,就是拋出Events的觸發條件。

  觸發Events的有下列的類型,分別代表不同的操作: job_started :JOB啟動; job_succeeded :JOB成功結束; job_failed :JOB執行失敗; job_broken :JOB被置為BROKEN狀態; job_completed :JOB達到最大運行次數,或者啟動並執行結束日期; job_stopped :JOB被STOP_JOB過程置為停止執行的狀態; job_sch_lim_reached :Job的schedule達到限定值; job_disabled :JOB被置於DISABLE狀態; job_chain_stalled :運行於chain的JOB被置於CHAIN_STALLED狀態; job_all_events :含上述提到的所有類型; job_run_completed :由於Job運行出錯、成功結束或被手動停止。

  起用raise_events後,Scheduler就會按照設定的觸發條件,當達到觸發條件時,即會拋出事件資訊到SYS.SCHEDULER$_EVENT_QUEUE隊列。

  例如,手動執行一次INSERT_TEST_TBL,看看是否向隊列中記錄資訊,操作如下:

SQL> exec dbms_scheduler.run_job('INSERT_TEST_TBL'); PL/SQL procedure successfully completed.

  執行下列指令碼,出隊資料:

SQL> set serveroutput on

SQL> DECLARE

  2    l_dequeue_options    DBMS_AQ.dequeue_options_t;

  3    l_message_properties DBMS_AQ.message_properties_t;

  4    l_message_handle     RAW(16);

  5    l_queue_msg          sys.scheduler$_event_info;

  6  BEGIN

  7    l_dequeue_options.consumer_name := 'TEST';

  8

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

 10                    dequeue_options    => l_dequeue_options,

 11                    message_properties => l_message_properties,

 12                    payload            => l_queue_msg,

 13                    msgid              => l_message_handle);

 14    COMMIT;

 15

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

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

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

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

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

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

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

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

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

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

 26  END;

 27  /

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啟動。實際上job:INSERT_TEST_TBL執行一次至少會向隊列中插入兩條event資訊,一條為JOB_STARTED,一條則為JOB_SUCCEEDED(也可能是JOB_FAILED),這裡不詳細示範,感興趣的朋友不妨自行測試。 提示:SYS.SCHEDULER$_EVENT_QUEUE隊列基於SYS.SCHEDULER$_EVENT_QTAB隊列表,因此查詢SYS.SCHEDULER$_EVENT_QTAB也可以擷取上述的資訊。

  SYS.SCHEDULER$_EVENT_QUEUE 是一個固定隊列,實際應用的過程中,DBA應該根據實際情況,將該表存取權限授予相關使用者,以便順利出隊該隊列中的events資訊。

  另外,友情提醒,預設情況下Scheduler僅保留最近24小時的Events資訊,如果希望修改該設定的話,可以通過SET_SCHEDULER_ATTRIBUTE過程,修改scheduler的event_expiry_time屬性,該項屬性的屬性值以秒為單位。 4.2 Application拋出的Events

  首先要說明,這裡所說的Application是個代詞,即可以表示ORACLE資料庫之外的應用程式,也可以是ORACLE資料庫中的PROCEDURE等對象,總之你就將其理解成使用者自己建立的對象就好了。

  Scheduler 能夠拋出Events讓外部應用處理,外部的應用也可以拋出Events讓Scheduler啟動job處理,不過並不是任何job都能夠對外部應用拋出的Events做出響應,必須在建立jobs時明確指定響應的事件。那麼如何指定呢。依靠下列兩個附加的參數: queue_spec :指定外部應用拋出的events訊息入隊的隊列名; event_condition :指定觸發job啟動的條件,這一參數的參數值在設定時應當基於事件訊息的自身屬性,因為事件訊息在入隊時,訊息的屬性都是由application定義的,因此在設定觸發條件時,也應該根據這些屬性值就行設定。

  下面,我們就示範建立一個由event觸發啟動的job,在此之前,首先需要進行一些準備工具,比如建立隊列,由於隊列需要基於一個隊列表,因此在建立隊列之前,首先要建立一個隊列表,考慮到隊列表需要依賴一個物件類型,因此在建立隊列表之前,先得建立一個type.......複雜,具體的操作步驟如下,客官可要看仔細了:

SQL> create or replace type jss_type 1  as object

  2  (

  3    event_type         VARCHAR2( 1 0),

  4    object_owner       VARCHAR2( 30 ),

  5    object_name        VARCHAR2( 3 0)

  6  );

  7  /

Type created.

SQL> begin

  2    dbms_aqadm.create_queue_table(

  3      queue_table        => 'my_queue_tbl1',

  4      queue_payload_type => 'JSS_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, 準備工作完成,下面就來建立一個event觸發啟動的job,建立指令碼如下:

SQL> BEGIN

  2  DBMS_SCHEDULER.CREATE_JOB (

  3     job_name            =>  'EVENT_JOB_T1',

  4     job_type            =>  'STORED_PROCEDURE',

  5     job_action          =>  'P_INSERTINTOTEST',

  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.

  上述指令碼僅做示範,因此建立的job仍然執行P_INSERTINTOTEST過程。

  三思並不準備再編寫一套外部的應用來觸發,這裡僅為了示範application觸發job啟動的樣本,因此三思決定通過pl/sql直接向event_t1隊列中添加訊息的方式,觸發job的啟動,具體操作如下。

  首先要執行DBMS_AQADM.START_QUEUE過程,將event_t1置於允許入隊和出隊狀態(預設情況下建立的隊列是不允許出隊和入隊操作的),指令碼如下:

SQL> exec dbms_aqadm.start_queue(queue_name => 'event_t1',enqueue => true,dequeue => true); PL/SQL procedure successfully completed.

  執行入隊操作:

SQL> declare

  2    v_Message           jss_type1;

  3    v_EnqueueOptions    dbms_aq.enqueue_options_t;

  4    v_MessageProperties dbms_aq.message_properties_t;

  5    v_msg_handle        raw(16);

  6  begin

  7    v_message := jss_type1('OP_ SELECT ', user, 'tmpObj');

  8

  9    dbms_aq.enqueue(queue_name         => 'event_t1',

 10                    enqueue_options    => v_enqueueOptions,

 11                    message_properties => v_messageproperties,

 12                    payload            => v_message,

 13                    msgid              => v_msg_handle);

 14    commit;

 15

 16  end;

 17  / PL/SQL procedure successfully completed.

  查詢隊列表中的資料:

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.