Вопрос по plsql, queue, callback – Каков синтаксис для создания подписчика очереди в PL / SQL?

0

Я пытаюсь создать очередь и обратный вызов, который запускается, когда сообщение ставится в очередь, но я не могу получить обратный вызов для запуска. Что я делаю неправильно?

У меня есть триггер, который ставит сообщение в очередь, и я вижу его в таблице сообщений очереди, и я могу удалить его из очереди вручную и обработать, я просто не могу получить обратный вызов для запуска при постановке в очередь.

BEGIN    
DBMS_AQADM.CREATE_QUEUE_TABLE (
  queue_table        => 'queue_message_table',
  queue_payload_type => 'queue_message_type',
  multiple_consumers => TRUE);

DBMS_AQADM.CREATE_QUEUE (
  queue_name  => 'message_queue',
  queue_table => 'queue_message_table');
DBMS_AQADM.START_QUEUE (queue_name => 'message_queue');
END;

CREATE OR REPLACE PROCEDURE queue_callback(
  context RAW, reginfo  SYS.AQ$_REG_INFO, descr SYS.AQ$_DESCRIPTOR, payload  RAW, payloadl NUMBER) AS

    queue_options       DBMS_AQ.DEQUEUE_OPTIONS_T;
    message_properties  DBMS_AQ.MESSAGE_PROPERTIES_T;
    my_message          queue_message_type;
    ret                 varchar2(200);
    message_id          RAW(16);
BEGIN
    DBMS_OUTPUT.PUT_LINE('Callback');
    queue_options.msgid := descr.msg_id;
    queue_options.consumer_name := descr.consumer_name;

    DBMS_AQ.DEQUEUE(
        queue_name => descr.queue_name,
        dequeue_options => queue_options,
        message_properties => message_properties,
        payload => my_message,
        msgid => message_id );
    ret := handle_message(my_message);
    commit;
END;

BEGIN
  DBMS_AQADM.ADD_SUBSCRIBER (queue_name => 'message_queue',
    subscriber => SYS.AQ$_AGENT('queue_subscriber', 'message_queue',NULL));
  DBMS_AQ.REGISTER (
    SYS.AQ$_REG_INFO_LIST(
      SYS.AQ$_REG_INFO(
        'MESSAGE_QUEUE:QUEUE_SUBSCRIBER',
        DBMS_AQ.NAMESPACE_AQ,
        'plsql://QUEUE_CALLBACK',
        HEXTORAW('FF')
      )
    ), 1
  );
END;
Вы это исправили? У меня та же проблема:stackoverflow.com/questions/30502535/… SaintLike

Ваш Ответ

2   ответа
1

общалось опроблемы с Oracle Aq. In particular I've followed эта ссылка создать свой собственный пример, выполнив демонстрацию в корпоративной базе данных Oracle 11gR2. Я смог поставить в очередь, удалить из очереди, очистить очередь, но прослушиватель, созданный с помощью Dbms_Aq.Register, не работал. Я запустил тот же пример загрузки базы данных Oracle 11g R2 xe, и это сработало.

Тот же пример был запущен в экземпляре Oracle 10gR2, и он работает отлично.

Есть некоторые вещи, которые вы должны быть осторожны при использовании aq:

use the appropriate parameters adding the subscriber use the appropriate namespace registering the listener with Dbms_Aq.Register use the multiple consumers flag declaring the queue table use the appropriate permissions to packages and to handle the queues use the qualified name of the queues in some cases if it didn't works.

& APOS; Сначала создайте схему

connect / as sysdba
-- @?/rdbms/admin/dbmsaqad.sql --(install if you don't have aq installed yet)

-- create the user and permissions
create user aqadmin identified by aqadmin default tablespace users temporary tablespace temp;
GRANT create session TO aqadmin;
grant connect, resource to aqadmin;
GRANT aq_administrator_role TO aqadmin IDENTIFIED BY aqadmin;
GRANT execute ON dbms_aq TO aqadmin;
GRANT execute ON dbms_aqadm TO aqadmin;

Создайте объекты ddl

CREATE TABLE demo_queue_message_table
( message VARCHAR2(4000) );

Создайте aq-объекты

create or replace type demo_queue_payload_type as object(message varchar2(4000)) ;
/

begin
  DBMS_AQADM.CREATE_QUEUE_TABLE (queue_table => 'demo_queue_table', queue_payload_type => 'demo_queue_payload_type',multiple_consumers => TRUE);
  DBMS_AQADM.CREATE_QUEUE (queue_name => 'demo_queue', queue_table => 'demo_queue_table');
  DBMS_AQADM.START_QUEUE('demo_queue');
end;
/

CREATE or replace PROCEDURE demo_queue_callback_procedure(
                 context  RAW,
                 reginfo  SYS.AQ$_REG_INFO,
                 descr    SYS.AQ$_DESCRIPTOR,
                 payload  RAW,
                 payloadl NUMBER
                 ) AS

   r_dequeue_options    DBMS_AQ.DEQUEUE_OPTIONS_T;
   r_message_properties DBMS_AQ.MESSAGE_PROPERTIES_T;
   v_message_handle     RAW(16);
   o_payload            demo_queue_payload_type;

BEGIN

   r_dequeue_options.msgid := descr.msg_id;
   r_dequeue_options.consumer_name := descr.consumer_name;

   DBMS_AQ.DEQUEUE(
      queue_name         => descr.queue_name,
      dequeue_options    => r_dequeue_options,
      message_properties => r_message_properties,
      payload            => o_payload,
      msgid              => v_message_handle
      );

   INSERT INTO demo_queue_message_table ( message )
   VALUES ( 'Message [' || o_payload.message || '] ' ||
            'dequeued at [' || TO_CHAR( SYSTIMESTAMP,
                                        'DD-MON-YYYY HH24:MI:SS.FF3' ) || ']' );
   COMMIT;

END;
/


BEGIN

   DBMS_AQADM.ADD_SUBSCRIBER (
      queue_name => 'demo_queue',
      subscriber => SYS.AQ$_AGENT(
                       'demo_queue_subscriber',
                       NULL,
                       NULL )
      );

    DBMS_AQ.REGISTER (
       SYS.AQ$_REG_INFO_LIST(
          SYS.AQ$_REG_INFO(
             'DEMO_QUEUE:DEMO_QUEUE_SUBSCRIBER',
             DBMS_AQ.NAMESPACE_AQ,
             'plsql://DEMO_QUEUE_CALLBACK_PROCEDURE',
             HEXTORAW('FF')
             )
          ),
       1
       );
END;
/

И, наконец, проверить очередь

DECLARE

   r_enqueue_options    DBMS_AQ.ENQUEUE_OPTIONS_T;
   r_message_properties DBMS_AQ.MESSAGE_PROPERTIES_T;
   v_message_handle     RAW(16);
   o_payload            demo_queue_payload_type;

BEGIN

   o_payload := demo_queue_payload_type(
                   TO_CHAR(SYSTIMESTAMP, 'DD-MON-YYYY HH24:MI:SS.FF3' )
                   );

   DBMS_AQ.ENQUEUE(
      queue_name         => 'demo_queue',
      enqueue_options    => r_enqueue_options,
      message_properties => r_message_properties,
      payload            => o_payload,
      msgid              => v_message_handle
      );

  COMMIT;

END;
/
1

dbms_aqadm.start_queue), вы тоже ничего не ставите в очередь (dbms_aq.enqueue).

Я рекомендую следовать этомудемонстрация.

Определенно есть сообщения, попадающие в очередь, я их вижу. Что-то не так в синтаксисе создания обратного вызова. Michael Sofaer
Ссылка на него есть в вызове AQ.REGISTER, она в конструкторе REG_INFO. Это похоже на то, как это делают онлайн-демоверсии, но, очевидно, я что-то упустил. Вы знаете, куда идет ссылка на обратный вызов? Michael Sofaer
Это какая-то помощь:forums.oracle.com/forums/thread.jspa?threadID=477055
Я заметил, что в ваших вызовах API AQ нет ссылки на queue_callback.

Похожие вопросы