खोज…


टिप्पणियों

  • dbms_aqadm.create_queue_table द्वारा बनाई गई तालिकाओं के खिलाफ कभी भी डीडीएल या dbms_aqadm.create_queue_table उपयोग न करें। इन तालिकाओं के साथ काम करने के लिए केवल dbms_aqadm और dbms_aq का उपयोग करें। ओरेकल कई सहायक टेबल, इंडेक्स आदि बना सकता है, जिनके बारे में आपको जानकारी नहीं होगी। तालिका के विरुद्ध डीडीएल या डीएमएल को मैन्युअल रूप से चलाना आपको एक परिदृश्य में ले जा सकता है जहां स्थिति को हल करने के लिए ओरेकल समर्थन को आपको तालिका और कतारों को छोड़ने और पुन: बनाने की आवश्यकता होगी।

  • यह दृढ़ता से अनुशंसा की जाती है कि आप प्रतीक्षा विकल्प के लिए dbms_aq.forever उपयोग न करें। इससे अतीत में समस्याएँ उत्पन्न हुई हैं क्योंकि Oracle अनावश्यक रूप से काम करने वाली कतारों को काम करने के लिए अत्यधिक संख्या में श्रमिक नौकरियों का समय निर्धारण शुरू कर सकता है (Oracle Doc ID 2001165.1 देखें)।

  • यह अनुशंसा की जाती है कि आप AQ_TM_PROCESSES पैरामीटर को 10.1 और बाद के संस्करण में सेट न करें। विशेष रूप से इसे शून्य पर सेट करने से बचें क्योंकि यह QMON पृष्ठभूमि की नौकरी को अक्षम कर देगा जो कतारों को बनाए रखने के लिए आवश्यक है। आप निम्न आदेश का उपयोग करके डेटाबेस को पुनः आरंभ करने के लिए इस मान को Oracle डिफ़ॉल्ट पर रीसेट कर सकते हैं। alter system reset aq_tm_processes scope=spfile sid='*';

सरल निर्माता / उपभोक्ता

अवलोकन

एक कतार बनाएं जिसे हम एक संदेश भेज सकें। ओरेकल हमारी संग्रहीत प्रक्रिया को सूचित करेगा कि एक संदेश को लागू किया गया है और काम किया जाना चाहिए। हम कुछ उपप्रोग्रामों को भी जोड़ेंगे, जिनका उपयोग हम आपातकाल में संदेशों को विचलित होने से रोकने के लिए कर सकते हैं, फिर से छेड़छाड़ की अनुमति दे सकते हैं, और सभी संदेशों के माध्यम से काम करने के लिए एक साधारण बैच की नौकरी चला सकते हैं।

इन उदाहरणों का परीक्षण Oracle डेटाबेस 12c एंटरप्राइज एडिशन रिलीज़ 12.1.0.2.0 - 64bit उत्पादन पर किया गया था।

कतार बनाएं

हम एक संदेश प्रकार, एक कतार तालिका बनाएंगे जो संदेशों को पकड़ सकती है, और एक कतार। कतार में संदेशों को प्राथमिकता से पहले हटा दिया जाएगा, फिर उनका एनक्यू टाइम होगा। अगर कुछ भी गलत हो जाता है तो संदेश काम कर जाता है और डीक्यू लुढ़क जाता है। AQ 3600 सेकंड बाद मैसेज को उपलब्ध कराएगा। इसे अपवाद कतार में ले जाने से पहले यह 48 बार करेगा।

create type message_t as object 
   (
   sender  varchar2 ( 50 ),
   message varchar2 ( 512 )
   );
/
-- Type MESSAGE_T compiled
begin dbms_aqadm.create_queue_table(
     queue_table        => 'MESSAGE_Q_TBL',
     queue_payload_type => 'MESSAGE_T',
     sort_list          => 'PRIORITY,ENQ_TIME',
     multiple_consumers =>  false,
     compatible         => '10.0.0');
  end;
/
-- PL/SQL procedure successfully completed.
begin dbms_aqadm.create_queue(
     queue_name          => 'MESSAGE_Q',
     queue_table         => 'MESSAGE_Q_TBL',
     queue_type          =>  0,
     max_retries         =>  48,
     retry_delay         =>  3600,
     dependency_tracking =>  false);
  end;
/
-- PL/SQL procedure successfully completed.

अब जब हमारे पास संदेश डालने की जगह है तो कतार में संदेशों को प्रबंधित करने और काम करने के लिए एक पैकेज बनाएं।

create or replace package message_worker_pkg
is
   queue_name_c constant varchar2(20) := 'MESSAGE_Q';
   
   -- allows the workers to process messages in the queue
   procedure enable_dequeue;

   -- prevents messages from being worked but will still allow them to be created and enqueued
   procedure disable_dequeue;

   -- called only by Oracle Advanced Queueing.  Do not call anywhere else.
   procedure on_message_enqueued (context        in raw,
                                  reginfo        in sys.aq$_reg_info,
                                  descr          in sys.aq$_descriptor,
                                  payload        in raw,
                                  payloadl       in number);

   -- allows messages to be worked if we missed the notification (or a retry
   -- is pending)
   procedure work_old_messages;
   
end;
/

create or replace package body message_worker_pkg
is
   -- raised by Oracle when we try to dequeue but no more messages are ready to
   -- be dequeued at this moment
   no_more_messages_ex          exception;
   pragma exception_init (no_more_messages_ex,
                          -25228);

   -- allows the workers to process messages in the queue
   procedure enable_dequeue
   as
   begin
      dbms_aqadm.start_queue (queue_name => queue_name_c, dequeue => true);
   end enable_dequeue;

   -- prevents messages from being worked but will still allow them to be created and enqueued
   procedure disable_dequeue
   as
   begin
      dbms_aqadm.stop_queue (queue_name => queue_name_c, dequeue => true, enqueue => false);
   end disable_dequeue;

   procedure work_message (message_in in out nocopy message_t)
   as
   begin
      dbms_output.put_line ( message_in.sender || ' says ' || message_in.message );
   end work_message;

   -- called only by Oracle Advanced Queueing.  Do not call anywhere else.

   procedure on_message_enqueued (context        in raw,
                                  reginfo        in sys.aq$_reg_info,
                                  descr          in sys.aq$_descriptor,
                                  payload        in raw,
                                  payloadl       in number)
   as
      pragma autonomous_transaction;
      dequeue_options_l      dbms_aq.dequeue_options_t;
      message_id_l           raw (16);
      message_l              message_t;
      message_properties_l   dbms_aq.message_properties_t;
   begin
      dequeue_options_l.msgid         := descr.msg_id;
      dequeue_options_l.consumer_name := descr.consumer_name;
      dequeue_options_l.wait          := dbms_aq.no_wait;
      dbms_aq.dequeue (queue_name           => descr.queue_name,
                       dequeue_options      => dequeue_options_l,
                       message_properties   => message_properties_l,
                       payload              => message_l,
                       msgid                => message_id_l);
      work_message (message_l);
      commit;
   exception
      when no_more_messages_ex
      then
         -- it's possible work_old_messages already dequeued the message
         commit;
      when others
      then
         -- we don't need to have a raise here.  I just wanted to point out that
         -- since this will be called by AQ throwing the exception back to it
         -- will have it put the message back on the queue and retry later
         raise;
   end on_message_enqueued;

   -- allows messages to be worked if we missed the notification (or a retry
   -- is pending)
   procedure work_old_messages
   as
      pragma autonomous_transaction;
      dequeue_options_l      dbms_aq.dequeue_options_t;
      message_id_l           raw (16);
      message_l              message_t;
      message_properties_l   dbms_aq.message_properties_t;
   begin
      dequeue_options_l.wait       := dbms_aq.no_wait;
      dequeue_options_l.navigation := dbms_aq.first_message;

      while (true) loop -- way out is no_more_messages_ex
         dbms_aq.dequeue (queue_name           => queue_name_c,
                          dequeue_options      => dequeue_options_l,
                          message_properties   => message_properties_l,
                          payload              => message_l,
                          msgid                => message_id_l);
         work_message (message_l);
         commit;
      end loop;
   exception
      when no_more_messages_ex
      then
         null;
   end work_old_messages;
end;

इसके बाद AQ को बताएं कि जब कोई संदेश MESSAGE_Q (और प्रतिबद्ध) के लिए लागू होता है, तो हमारी कार्यविधि को सूचित करें कि यह काम करना है। AQ इसे संभालने के लिए अपने स्वयं के सत्र में एक नौकरी शुरू करेगा।

begin
  dbms_aq.register (
     sys.aq$_reg_info_list (
        sys.aq$_reg_info (user || '.' || message_worker_pkg.queue_name_c,
                          dbms_aq.namespace_aq,
                          'plsql://' || user || '.message_worker_pkg.on_message_enqueued',
                          hextoraw ('FF'))),
     1);
  commit;
end; 

कतार शुरू करें और एक संदेश भेजें

declare
   enqueue_options_l      dbms_aq.enqueue_options_t;
   message_properties_l   dbms_aq.message_properties_t;
   message_id_l           raw (16);
   message_l              message_t;
begin
   -- only need to do this next line ONCE
   dbms_aqadm.start_queue (queue_name => message_worker_pkg.queue_name_c, enqueue => true , dequeue => true);
   
   message_l := new message_t ( 'Jon', 'Hello, world!' );
   dbms_aq.enqueue (queue_name           => message_worker_pkg.queue_name_c,
                    enqueue_options      => enqueue_options_l,
                    message_properties   => message_properties_l,
                    payload              => message_l,
                    msgid                => message_id_l);
   commit;
end;


Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow