如何在 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_vc
或 bytes_raw
。但是,有效负载只有大约 500 个字符长。 (我们确实设置了几个 header,但如果我理解正确的话,它们会进入一个单独的 header 'field'。
然而,主要问题是当用户 B 想要将 CLOB 大小的消息插入模式 A 时,我们得到错误 ORA-01031: insufficient privileges
。作为用户 A 授权,问题不会出现。
- 我们如何授予用户 B 必要的权限?
- 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 的方法,也许值得检查一下
我们将模式 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_vc
或 bytes_raw
。但是,有效负载只有大约 500 个字符长。 (我们确实设置了几个 header,但如果我理解正确的话,它们会进入一个单独的 header 'field'。
然而,主要问题是当用户 B 想要将 CLOB 大小的消息插入模式 A 时,我们得到错误 ORA-01031: insufficient privileges
。作为用户 A 授权,问题不会出现。
- 我们如何授予用户 B 必要的权限?
- 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 的方法,也许值得检查一下