如何在 Oracle Advanced Queuing 中将 CLOB 权限授予外部 queue 用户?

How do I grant CLOB privileges to a foreign queue user in Oracle Advanced Queuing?

我们将模式 A 的以下权限授予用户 B,以便插入 Oracle 12c 中的 queue:

GRANT CREATE SESSION TO &UNAME_ENQUEUE;
GRANT EXECUTE ON SYS.DBMS_AQ TO &UNAME_ENQUEUE;
GRANT EXECUTE ON SYS.DBMS_AQADM TO &UNAME_ENQUEUE;
GRANT EXECUTE ON SYS.DBMS_AQIN TO &UNAME_ENQUEUE;
GRANT EXECUTE ON SYS.DBMS_AQJMS TO &UNAME_ENQUEUE;

...

    DBMS_AQADM.GRANT_QUEUE_PRIVILEGE (
            privilege        =>    'ENQUEUE',
            queue_name       =>    v_queue_name,
            grantee          =>    v_grantee_name,
            grant_option     =>    FALSE);

queuetable定义为:

dbms_aqadm.create_queue_table(queue_table => 'queue_name_t', queue_payload_type => 'sys.aq$_jms_message');

...

GRANT INSERT ON &USERNAME..queue_name_t TO &UNAME_ENQUEUE;
GRANT SELECT ON &USERNAME..queue_name_t TO &UNAME_ENQUEUE;

queue通过JMS接口访问。我们注意到,对于大小大于 x 的消息,Oracle 希望将消息负载存储为 CLOB。首先,我们不知道x。根据 the Specification of the JMS message type 猜测,文本消息应为 4000,字节消息应为 2000,因为较小的消息适合 text_vcbytes_raw。但是,有效负载只有大约 500 个字符长。 (我们确实设置了几个 header,但如果我理解正确的话,它们会进入一个单独的 header 'field'。

然而,主要问题是当用户 B 想要将 CLOB 大小的消息插入模式 A 时,我们得到错误 ORA-01031: insufficient privileges。作为用户 A 授权,问题不会出现。

  1. 我们如何授予用户 B 必要的权限?
  2. Oracle 何时选择使用 (C)LOB?

1.我们如何才能授予用户 B 必要的权限?

请为 ORA-01031: insufficient privileges 提供更广泛的异常堆栈,这条消息并没有说明根本原因 这是我的想法。

在 Oracle DB 中,有一个 JMS 类型入队的先决条件,例如 sys.aq$_jms_message 尝试为您的队列启用它。

begin
dbms_aqadm.enable_jms_types(queue_table => v_queue_name);
end;
/

顺便说一句。具有 LOB 的负载需要显式 Select、对队列 table

的插入和更新权限

2.When Oracle 是否选择使用 (C)LOB?

无需从文档中猜测。您用于队列的有效负载类型将文本消息存储在 text_vc 或 text_lob 变量中。你写了 the payload is only about 500 characters long,正如你在类型定义字段上看到的那样被声明为 varchar2(4000) 这并不一定意味着它是关于字符的,它也可以是关于字节的——当没有明确的声明时它是确定的通过 nls 参数(另见 select * from V$NLS_PARAMETERS t where t.PARAMETER = 'NLS_LENGTH_SEMANTICS';

对于 aq$_jms_text_message 有 2 个选项,要么您提供大对象数据类型作为输入参数,要么您的消息 >= 4000,这就是 Oracle 将其存储为 clob 的原因。 aq$_jms_bytes_message 的情况类似(如果 bytes_lob 的长度为 =< 32767 vs BLOB 中的有效载荷)

SYS.AQ$_JMS_MESSAGE (
  text_vc       varchar2(4000),
  text_lob      clob,
...

  -- set_text sets payload in varchar2 into text_vc if the length of
  -- payload is <= 4000, into text_lob if otherwise.
  MEMBER PROCEDURE set_text ( payload IN VARCHAR2 ),
..
  --
  -- set_text sets payload in clob in text_lob.
  MEMBER PROCEDURE set_text ( payload IN CLOB ),
...
)

顺便说一句。对于使用 HTTP 协议和安全队列的代理,也有类似 DBMS_AQADM.ENABLE_DB_ACCESS 的方法,也许值得检查一下