0

根据 Oracle 的 Streams Advanced Queuing User's Guide and Reference:“为了存储 RAW 类型的有效负载,Oracle Streams AQ 创建一个队列表,其中 LOB 列作为有效负载存储库。有效负载的最大大小取决于您使用的编程接口来访问 Oracle Streams AQ。对于 PL/SQL、Java 和预编译器,限制为 32K;对于 OCI,限制为 4G。

所以我的问题是我们如何确定有效载荷/消息的大小是否超过32K?

现有的 Oracle 过程如下所示:

CREATE OR REPLACE procedure PRC_ordercreated(P_MSG in clob, P_MSGID out raw)
is
  V_ENQUEUEOPTIONS SYS.DBMS_AQ.ENQUEUE_OPTIONS_T;
  V_MESSAGEPROPERTIES SYS.DBMS_AQ.MESSAGE_PROPERTIES_T;

  V_QUEUENAME varchar2(35) := 'QUE_ordercreated';
begin
  V_MESSAGEPROPERTIES.USER_PROPERTY := SYS.ANYDATA.CONVERTTIMESTAMPTZ(systimestamp);

  /*  when the payload message exceeds 32K, the message will be stored in a separate table
  */
  
  SYS.DBMS_AQ.ENQUEUE(
    QUEUE_NAME => V_QUEUENAME,
    PAYLOAD => SYS.UTL_RAW.CAST_TO_RAW(P_MSG),
    ENQUEUE_OPTIONS  => V_ENQUEUEOPTIONS,
    MESSAGE_PROPERTIES => V_MESSAGEPROPERTIES,
    MSGID => P_MSGID);
    
  insert into QUEUE_OVERSIZEDMESSAGE(
    MSGID,
    LARGEMESSAGE)
  values (
    P_MSGID,
    P_MSG);
end;
/

[更新] 在@kfinity 的回答的帮助下,请在下面找到我的最终解决方案:

CREATE OR REPLACE procedure PRC_ENQUEUE(P_MSG in clob, P_MSGID out raw)
is
  V_ENQUEUEOPTIONS SYS.DBMS_AQ.ENQUEUE_OPTIONS_T;
  V_MESSAGEPROPERTIES SYS.DBMS_AQ.MESSAGE_PROPERTIES_T;
  V_QUEUENAME varchar2(16) := 'QUE_ORDERCREATED';
  V_MAXPAYLOADSIZE number := 32000;
begin
  V_MESSAGEPROPERTIES.USER_PROPERTY := SYS.ANYDATA.CONVERTTIMESTAMPTZ(systimestamp);

  /* When the payload message exceeds 32K, the message will be stored in a separate table
  */
  if SYS.UTL_RAW.LENGTH(SYS.UTL_RAW.CAST_TO_RAW(P_MSG)) > V_MAXPAYLOADSIZE then
    SYS.DBMS_AQ.ENQUEUE(
      QUEUE_NAME => V_QUEUENAME,
      PAYLOAD => SYS.UTL_RAW.CAST_TO_RAW('IsLargeMessage'),
      ENQUEUE_OPTIONS  => V_ENQUEUEOPTIONS,
      MESSAGE_PROPERTIES => V_MESSAGEPROPERTIES,
      MSGID => P_MSGID);

    insert into QUEUE_LARGEMESSAGE(
      MSGID,
      LARGEMESSAGE,
      CREATIONDATETIME,
      LASTMODIFICATIONDATETIME)
    values (
      P_MSGID,
      P_MSG,
      systimestamp,
      systimestamp);
  else
    SYS.DBMS_AQ.ENQUEUE(
      QUEUE_NAME => V_QUEUENAME,
      PAYLOAD => SYS.UTL_RAW.CAST_TO_RAW(P_MSG),
      ENQUEUE_OPTIONS  => V_ENQUEUEOPTIONS,
      MESSAGE_PROPERTIES => V_MESSAGEPROPERTIES,
      MSGID => P_MSGID);
  end if;
end;
/
4

1 回答 1

0

我会添加一个 IF 语句来检查原始变量的长度。最大大小为 32767。

CREATE OR REPLACE procedure PRC_ordercreated(P_MSG in clob, P_MSGID out raw)
is
  V_ENQUEUEOPTIONS SYS.DBMS_AQ.ENQUEUE_OPTIONS_T;
  V_MESSAGEPROPERTIES SYS.DBMS_AQ.MESSAGE_PROPERTIES_T;

  V_QUEUENAME varchar2(35) := 'QUE_ordercreated';
begin
  V_MESSAGEPROPERTIES.USER_PROPERTY := SYS.ANYDATA.CONVERTTIMESTAMPTZ(systimestamp);

  /*  when the payload message exceeds 32K, the message will be stored in a separate table
  */
  
  if SYS.UTL_RAW.LENGTH(SYS.UTL_RAW.CAST_TO_RAW(P_MSG)) < 32768 then
    SYS.DBMS_AQ.ENQUEUE(
      QUEUE_NAME => V_QUEUENAME,
      PAYLOAD => SYS.UTL_RAW.CAST_TO_RAW(P_MSG),
      ENQUEUE_OPTIONS  => V_ENQUEUEOPTIONS,
      MESSAGE_PROPERTIES => V_MESSAGEPROPERTIES,
      MSGID => P_MSGID);
  else
    insert into QUEUE_OVERSIZEDMESSAGE(
      MSGID,
      LARGEMESSAGE)
    values (
      P_MSGID,
      P_MSG);
  end if;
end;
/

如果您想在有效负载太大时仍想将消息添加到队列中,您可能需要对此进行调整,也许使用占位符有效负载来代替?

于 2021-11-18T17:15:41.130 回答