首页 > 解决方案 > 如何在 Oracle Advanced Queuing 中向外部队列用户授予 CLOB 权限?

问题描述

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

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);

队列表定义为:

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;

通过 JMS 接口访问队列。我们注意到对于大小大于 x 的消息,Oracle 希望将消息负载存储为 CLOB。首先,我们不知道 x。根据 JMS 消息类型的规范猜测,文本消息应该是 4000,字节消息应该是 2000,因为较小的消息可以放入text_vcor bytes_raw。然而,有效载荷只有大约 500 个字符长。(我们确实设置了几个标题,但如果我正确理解类型,它们会进入单独的标题“字段”)。

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

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

标签: oracleoracle-aq

解决方案


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 的负载需要对队列表的明确选择、插入和更新权限

2.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 (payload IN RAW 如果 bytes_lob 的长度 =< 32767 vs payload IN 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 ),
...
)

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


推荐阅读