加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

Oracle Advance Queue – Dequeue无法正常工作

发布时间:2020-12-12 13:14:51 所属栏目:百科 来源:网络整理
导读:我似乎无法找到问题的解决方案,我已经坚持了几个小时. 我正在使用Oracle AQ: Dbms_Aqadm.Create_Queue_Table(Queue_Table = 'ITEM_EVENT_QT',Queue_Payload_Type = 'ITEM_EVENT',Multiple_Consumers = TRUE); Dbms_Aqadm.Create_Queue(Queue_Name = 'ITEM_E
我似乎无法找到问题的解决方案,我已经坚持了几个小时.

我正在使用Oracle AQ:

Dbms_Aqadm.Create_Queue_Table(Queue_Table        => 'ITEM_EVENT_QT',Queue_Payload_Type => 'ITEM_EVENT',Multiple_Consumers => TRUE);

       Dbms_Aqadm.Create_Queue(Queue_Name          => 'ITEM_EVENT_QUEUE',Queue_Table         => 'ITEM_EVENT_QT',Max_Retries         => 5,Retry_Delay         => 0,Retention_Time      => 432000,-- 5 DAYS
                              Dependency_Tracking => FALSE,COMMENT             => 'Item Event Queue');
       -- START THE QUEUE
       Dbms_Aqadm.Start_Queue('ITEM_EVENT_QUEUE');
       -- GRANT QUEUE PRIVILEGES
       Dbms_Aqadm.Grant_Queue_Privilege(Privilege    => 'ALL',Queue_Name   => 'ITEM_EVENT_QUEUE',Grantee      => 'PUBLIC',Grant_Option => FALSE);
    END;

这是我的一位订阅者:

Dbms_Aqadm.Add_Subscriber(Queue_Name => 'ITEM_EVENT_QUEUE',Subscriber => Sys.Aq$_Agent('ITEM_SUBSCRIBER_1',NULL,NULL),rule   =>  'tab.user_data.header.thread_no = 1');

   Dbms_Aq.Register(Sys.Aq$_Reg_Info_List(Sys.Aq$_Reg_Info('ITEM_EVENT_QUEUE:ITEM_SUBSCRIBER_1',Dbms_Aq.Namespace_Aq,'plsql://ITEM_API.GET_QUEUE_FROM_QUEUE',HEXTORAW('FF'))),1);

订户注册:

每当我的数据库上发生某个事件时,我都会使用触发器通过从我的ITEM_API包中调用以下过程将“事件”添加到我的AQ:

PROCEDURE ADD_EVENT_TO_QUEUE(I_EVENT       IN ITEM_EVENT,O_STATUS_CODE OUT VARCHAR2,O_ERROR_MSG   OUT VARCHAR2) IS

    ENQUEUE_OPTIONS    DBMS_AQ.ENQUEUE_OPTIONS_T;
    MESSAGE_PROPERTIES DBMS_AQ.MESSAGE_PROPERTIES_T;
    MESSAGE_HANDLE     RAW(16);
    EVENT              ITEM_EVENT;
    HEADER_PROP        HEADER_PROPERTIES;
  BEGIN
    EVENT                              := I_EVENT;
    EVENT.SEQ_NO                       := ITEM_EVENT_SEQ.NEXTVAL;
    ENQUEUE_OPTIONS.VISIBILITY         := DBMS_AQ.ON_COMMIT;
    ENQUEUE_OPTIONS.SEQUENCE_DEVIATION := NULL;
    MESSAGE_PROPERTIES.PRIORITY        := 1;
    MESSAGE_PROPERTIES.DELAY           := DBMS_AQ.NO_DELAY;
    MESSAGE_PROPERTIES.EXPIRATION      := DBMS_AQ.NEVER;
    HEADER_PROP                        := HEADER_PROPERTIES(1);
    EVENT.HEADER                       := HEADER_PROP;
    DBMS_AQ.ENQUEUE(QUEUE_NAME         => 'ITEM_EVENT_QUEUE',ENQUEUE_OPTIONS    => ENQUEUE_OPTIONS,MESSAGE_PROPERTIES => MESSAGE_PROPERTIES,PAYLOAD            => EVENT,MSGID              => MESSAGE_HANDLE);
  EXCEPTION
    WHEN OTHERS THEN
      ERROR_HANDLER.LOG_ERROR(NULL,EVENT.ITEM,EVENT.SEQ_NO,SQLCODE,SQLERRM,O_STATUS_CODE,O_ERROR_MSG);
      RAISE;
  END ADD_EVENT_TO_QUEUE;

并且它正在工作,因为当我检查我的AQ表时,我可以找到“事件”,但是我的出列方法不是dequeing,正如你在下面的图像中看到的那样,没有DEQ_TIME.

这是我的dequeue方法,也来自我的ITEM_API包:

PROCEDURE GET_QUEUE_FROM_QUEUE(CONTEXT  RAW,REGINFO  SYS.AQ$_REG_INFO,DESCR    SYS.AQ$_DESCRIPTOR,PAYLOAD  RAW,PAYLOADL NUMBER) IS

    R_DEQUEUE_OPTIONS    DBMS_AQ.DEQUEUE_OPTIONS_T;
    R_MESSAGE_PROPERTIES DBMS_AQ.MESSAGE_PROPERTIES_T;
    V_MESSAGE_HANDLE     RAW(16);
    I_PAYLOAD            ITEM_EVENT;
    L_PROC_EVENT         BOOLEAN;
    O_TARGETS            CFG_EVENT_STAGE_TBL;
    O_ERROR_MSG          VARCHAR2(300);
    O_STATUS_CODE        VARCHAR2(100);
  BEGIN
    R_DEQUEUE_OPTIONS.MSGID         := DESCR.MSG_ID;
    R_DEQUEUE_OPTIONS.CONSUMER_NAME := DESCR.CONSUMER_NAME;
    R_DEQUEUE_OPTIONS.DEQUEUE_MODE  := DBMS_AQ.REMOVE;
    --R_DEQUEUE_OPTIONS.WAIT          := DBMS_AQ.NO_WAIT;
    DBMS_AQ.DEQUEUE(QUEUE_NAME         => DESCR.QUEUE_NAME,DEQUEUE_OPTIONS    => R_DEQUEUE_OPTIONS,MESSAGE_PROPERTIES => R_MESSAGE_PROPERTIES,PAYLOAD            => I_PAYLOAD,MSGID              => V_MESSAGE_HANDLE);
    IF I_PAYLOAD IS NOT NULL THEN
      L_PROC_EVENT := PROCESS_EVENT(I_PAYLOAD,O_TARGETS,O_ERROR_MSG);
    END IF;
  EXCEPTION
    WHEN OTHERS THEN
      ERROR_HANDLER.LOG_ERROR(NULL,O_ERROR_MSG);
      RAISE;
  END GET_QUEUE_FROM_QUEUE;

难道我做错了什么?我怎样才能解决这个问题?我认为我的订阅者注册可能有问题,但我不确定.

编辑:我刚刚想出如果我删除订阅者和注册表,然后重新添加它们,他们会将所有消息出列.如果另一个事件被排队,它将保持不变(或直到我删除并再次添加订阅者):

状态为0且没有DEQ_TIME的记录是新记录.

我需要调度程序或类似的东西吗?

编辑:我已经为我的AQ添加了一个调度程序传播:

DBMS_AQADM.SCHEDULE_PROPAGATION('ITEM_EVENT_QUEUE');

甚至添加了next_time字段:

DBMS_AQADM.SCHEDULE_PROPAGATION('ITEM_EVENT_QUEUE',SYSDATE + 30/86400);

仍然无法正常工作.有什么建议?我猜AQ通知不起作用,我的回调程序永远不会被调用.我怎样才能解决这个问题?

编辑:我已经从包中删除了我的程序只是为了测试目的,所以我的队友可以编译ITEM_API包(我不知道是否重新编译包,可能会或可能不会对出列过程产生影响).
仍然无法正常工作.

解决方法

创建代码块并运行以下命令:

DECLARE
  dequeue_options      DBMS_AQ.dequeue_options_t;
  message_properties   DBMS_AQ.message_properties_t;
  message_handle       RAW (16);
  I_PAYLOAD            ITEM_EVENT;
  no_messages exception;
  msg_content          VARCHAR2 (4000);
  PRAGMA EXCEPTION_INIT (no_messages,-25228);
BEGIN
  dequeue_options.wait := DBMS_AQ.NO_WAIT;
  dequeue_options.consumer_name := 'ITEM_SUBSCRIBER_1';   
  dequeue_options.navigation := DBMS_AQ.FIRST_MESSAGE;
LOOP    
 DBMS_AQ.DEQUEUE (queue_name           => 'ITEM_EVENT_QUEUE',dequeue_options      => dequeue_options,message_properties   => message_properties,payload              => I_PAYLOAD,msgid                => message_handle
                     );
END LOOP;
  EXCEPTION
  WHEN no_messages
  THEN
     DBMS_OUTPUT.PUT_LINE ('No more messages left');
END;

让我知道您的排队邮件会发生什么.

您应该有一个表格,您可以在其中取消数据.

您是否还可以尝试在代理中添加enqueud表,然后将代理指定到出列表.

DECLARE
  aSubscriber sys.aq$_agent;
BEGIN 
  aSubscriber := sys.aq$_agent('ITEM_SUBSCRIBER_1','ITEM_EVENT_QUEUE',0);
  dbms_aqadm.add_subscriber
 ( queue_name     => 'ITEM_EVENT_QUEUE',subscriber     => aSubscriber);
END;
/

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读