1

我是 Oracle AQ 流程的新手,对异常队列有一些疑问。这是我的场景:

Oracle Database 19c 企业版 19.0.0.0.0 版

创建表和队列:

BEGIN

  DBMS_AQADM.CREATE_QUEUE_TABLE (
      QUEUE_TABLE  =>'ADD_QUEUE_TABLE',
      MULTIPLE_CONSUMERS   => TRUE,
      QUEUE_PAYLOAD_TYPE   => 'ADD_OBJECT_TYPE');

  DBMS_AQADM.CREATE_QUEUE (
      QUEUE_NAME  => 'ADD_QUEUE',
      QUEUE_TABLE => 'ADD_QUEUE_TABLE',
      max_retries => 6,
      retry_delay => 1800);

  DBMS_AQADM.START_QUEUE (QUEUE_NAME => 'ADD_QUEUE');

END;    
/

据我了解,它应该以 30 分钟的延迟重试出列 6 次,然后发送到异常队列。但就我而言,它确实将消息发送到异常队列很多。我希望您的输入知道我是否遗漏了什么或做错了什么。

入队:

CREATE PROCEDURE TXN_ENQUEUE_PROCEDURE (HN_TXN_SEQ IN NUMBER)
AS
  ENQUEUE_OPTIONS      DBMS_AQ.ENQUEUE_OPTIONS_T;
  MESSAGE_PROPERTIES   DBMS_AQ.MESSAGE_PROPERTIES_T;
  MESSAGE_HANDLE       RAW (16);
  MESSAGE             TXN_OBJECT_TYPE;
BEGIN
  MESSAGE := TXN_OBJECT_TYPE (HN_TXN_SEQ);
  DBMS_AQ.ENQUEUE (QUEUE_NAME           => 'FILE_QUEUE',
                   ENQUEUE_OPTIONS      => ENQUEUE_OPTIONS,
                   MESSAGE_PROPERTIES   => MESSAGE_PROPERTIES,
                   PAYLOAD              => MESSAGE,
                   MSGID                => MESSAGE_HANDLE);
  COMMIT;
END;
/

出队:

CREATE OR REPLACE PROCEDURE TXN_DEQUEUE_PROCEDURE (
  CONTEXT    RAW,
  REGINFO    SYS.AQ$_REG_INFO,
  DESCR      SYS.AQ$_DESCRIPTOR,
  PAYLOAD    RAW,
  PAYLOADL   NUMBER)
AS
  DEQUEUE_OPTIONS      DBMS_AQ.DEQUEUE_OPTIONS_T;
  MESSAGE_PROPERTIES   DBMS_AQ.MESSAGE_PROPERTIES_T;
  MESSAGE_HANDLE       RAW (16);
  MESSAGE              TXN_OBJECT_TYPE;
BEGIN
  DEQUEUE_OPTIONS.WAIT := DBMS_AQ.NO_WAIT;
  DEQUEUE_OPTIONS.CONSUMER_NAME := 'MYSUBSCRIBER';
  DEQUEUE_OPTIONS.NAVIGATION := DBMS_AQ.FIRST_MESSAGE;
  DEQUEUE_OPTIONS.MSGID := DESCR.MSG_ID;
  DEQUEUE_OPTIONS.CONSUMER_NAME := DESCR.CONSUMER_NAME;
  LOOP
    DBMS_AQ.DEQUEUE (QUEUE_NAME           => DESCR.QUEUE_NAME,
                     DEQUEUE_OPTIONS      => DEQUEUE_OPTIONS,
                     MESSAGE_PROPERTIES   => MESSAGE_PROPERTIES,
                     PAYLOAD              => MESSAGE,
                     MSGID                => MESSAGE_HANDLE);
    INSERT INTO MESSAGE_TABLE_SAMPLE  VALUES (MESSAGE.HN_TXN_SEQ);

    XYZ_PACKAGE.ABC_API (MESSAGE.HN_TXN_SEQ); ---- CALL API ----
    COMMIT;
  END LOOP;
END;    
/

当我执行入队时,如果应用程序出现故障或出于任何其他原因,消息将进入异常队列。如果我从异常队列中出列,是否需要在出列过程中提及(XYZ_PACKAGE.ABC_API (MESSAGE.HN_TXN_SEQ); ---- CALL API ----),否则它将像正常队列出列过程一样自动调用.

异常队列:

EXECUTE DBMS_AQADM.START_QUEUE('AQ$_FILE_QUEUE_TABLE_E', false, true);

DECLARE
  dequeue_options DBMS_AQ.dequeue_options_t;
  message_properties DBMS_AQ.message_properties_t;
  dq_msgid RAW(16);
  payload RAW(1);
  no_messages exception;
  pragma exception_init (no_messages, -25263);
  msg_count number(2);
  cursor c_msg_ids is
    select msg_id
    from aq$FILE_QUEUE_TABLE
    where queue = 'AQ$_FILE_QUEUE_TABLE_E';
BEGIN
  dequeue_options.consumer_name := null;
  dequeue_options.wait := DBMS_AQ.NO_WAIT;
  dequeue_options.navigation := DBMS_AQ.FIRST_MESSAGE;
  dequeue_options.dequeue_mode := dbms_aq.remove_nodata;
  For v_msg_id in c_msg_ids loop
    dequeue_options.msgid := v_msg_id.msg_id;
    msg_count := 0;
    DBMS_AQ.DEQUEUE(queue_name => 'sys.AQ$_FILE_QUEUE_TABLE_E',
                    dequeue_options => dequeue_options,
                    message_properties => message_properties,
                    payload => payload,
                    msgid => dq_msgid);
    dbms_output.put_line('Message id : '||v_msg_id.msg_id||' removed');
    msg_count := msg_count + 1;
    dequeue_options.msgid := null;
    dequeue_options.navigation := DBMS_AQ.NEXT_MESSAGE;
  END LOOP;
EXCEPTION
  WHEN no_messages THEN
    DBMS_OUTPUT.PUT_LINE ('No of Messages Removed: '||msg_count);
    COMMIT;
END;
/

执行上述操作后,它会从异常队列中删除消息。我需要在两者之间的任何地方提及( XYZ_PACKAGE.ABC_API (MESSAGE.HN_TXN_SEQ); ---- CALL API ----) 吗?

执行异常队列还是使用 max_retries 和 retry_delay 更好?

如果消息移动到异常队列,并且如果我运行查询以使它们出列。它们是否遵循与普通队列出列相同的机制并执行使用消息作为输入的任何其他 API?

谢谢!

4

0 回答 0