Oracle Advance Queue – Dequeue无法正常工作
我似乎无法找到问题的解决方案,我已经坚持了几个小时.
我正在使用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; / (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |