将持久消息与存储在云对象存储中的消息一起使用
DBMS_PIPE 程序包在自治 AI 数据库上具有扩展功能,可支持持久性消息传递,其中消息存储在云对象存储中。
关于使用 DBMS_PIPE 进行持久消息传递
通过使用 DBMS_PIPE 进行持久消息传递,一个或多个数据库会话可以在同一区域或跨区域与存储在云对象存储中的消息进行通信。
DBMS_PIPE 中的持久消息:
-
允许您发送和检索非常大的消息。
-
支持发送大量管道消息。
-
支持在单个数据库中、跨多个数据库以及不同区域的数据库之间发送和接收消息。
-
支持使用同一云对象存储位置 URI 的多个管道。
可以在任何支持的 DBMS_PIPE 类型中创建持久性消息传递管道:
-
隐式管道:使用
DBMS_PIPE.SEND_MESSAGE函数发送带有未知管道名称的消息时自动创建。 -
显式管道:使用用户指定的管道名称的
DBMS_PIPE.CREATE_PIPE函数创建。 -
公共管道:对
DBMS_PIPE软件包具有EXECUTE权限的任何用户均可访问。 -
专用管道:与管道创建者具有相同用户的会话可以访问。
注:Oracle 建议在发送或接收具有持久性消息传送的消息之前创建显式管道。使用 DBMS_PIPE.CREATE_PIPE 创建显式管道可确保使用所需的访问权限(公共或专用)(通过设置 private 参数)创建管道。
下面显示了具有持久性消息传送的 DBMS_PIPE 的常规工作流:
插图 database-pipe-persistent-messaging.svg 的说明
使用 DBMS_PIPE 的现有应用程序可以在极少更改的情况下继续运行。您可以使用登录触发器或使用其他一些初始化例程,为使用 DBMS_PIPE 的现有应用程序配置凭证对象和位置 URI。设置 DBMS_PIPE 身份证明和位置 URI 后,无需进行任何其他更改即可使用持久性消息传送。所有后续使用管道都将消息存储在云对象存储中,而不是存储在数据库内存中。这样,您可以将消息的存储方法从内存中更改为持久性云对象存储,且只需进行少量更改。
持久消息传递概述和功能
使用持久消息传递的 DBMS_PIPE 功能:
-
可以跨同一区域中的多个自治 AI 数据库实例或跨区域发送和检索消息。
-
持久消息可以保证仅由一个进程写入或读取。这可防止由于并发读取和写入而导致消息内容不一致。
DBMS_PIPE只允许一个操作,发送消息或接收消息在给定时间处于活动状态,并且这些操作由锁定机制保护。但是,如果由于正在进行的操作而无法执行某个操作,则进程会定期重试,直到达到timeout值为止。 -
DBMS_PIPE使用DBMS_CLOUD访问云对象存储。消息可以存储在受支持的任何云对象存储中。有关详细信息,请参阅云对象存储 URI 格式。 -
DBMS_PIPE使用DBMS_CLOUD访问云对象存储,并且提供了所有支持的身份证明类型:DBMS_CLOUD.CREATE_CREDENTIAL: See CREATE_CREDENTIAL procedure for more information.
DBMS_PIPE 权限授权和安全
DBMS_PIPE 过程在调用者的权限下运行。专用管道归当前用户所有,由用户创建的专用管道只能由同一用户使用。这适用于将消息存储到云对象存储的内存中管道和持久性消息传递管道。发送和接收消息在调用者的方案中运行。
使用将消息存储到云对象存储的专用管道,需要身份证明对象才能使用 location_uri 参数标识的云对象存储进行验证。调用用户必须对使用用于访问对象存储的 credential_name 参数指定的身份证明对象具有 EXECUTE 权限。
要使用公共管道,用户、数据库会话必须对 DBMS_PIPE 具有执行权限。对于使用持久消息传送并将消息存储到云对象存储的公共管道,用户、数据库会话必须对 DBMS_CLOUD 具有执行权限并对身份证明对象执行权限(或者您可以创建允许访问包含消息的位置 URI 的身份证明对象)。
DBMS_PIPE 限制
DBMS_PIPE 软件包不支持在使用不同字符集的数据库之间发送消息。例如,如果您有一个使用 AL32UTF8 的自治 AI 数据库实例和另一个使用 WE8MSWIN1252 的实例,则无法在这两个数据库之间发送带有 DBMS_PIPE 的消息。在这种情况下,如果尝试在这两个数据库之间发送带有 DBMS_PIPE 的消息,系统将引发错误 ORA-12704。
有关详细信息,请参阅自治 AI 数据库的字符集选择。
创建显式持久性管道并发送消息
描述创建具有指定管道名称(显式管道)的持久性管道的步骤。
-
使用过程
DBMS_CLOUD.CREATE_CREDENTIAL存储对象存储身份证明。例如:BEGIN DBMS_CLOUD.CREATE_CREDENTIAL( credential_name => 'my_persistent_pipe_cred', username => 'adb_user@example.com', password => 'password' ); END; /此操作以加密格式将身份证明存储在数据库中。可以将任何名称用于身份证明名称。请注意,除非对象存储身份证明发生更改,否则此步骤仅需要一次。存储身份证明后,您可以使用相同的身份证明名称访问云对象存储以使用
DBMS_PIPE发送和接收消息。有关参数的详细信息,请参见 CREATE_CREDENTIAL Procedure 。对于 Oracle Cloud Infrastructure Object Storage,身份证明需要使用原生 Oracle Cloud Infrastructure 验证。
注:一些工具(如 SQL*Plus 和 SQL Developer)使用 & 符号 (
&) 作为特殊字符。如果口令中有 & 符号,请使用示例中所示的这些工具中的SET DEFINE OFF命令禁用特殊字符并正确创建身份证明。 -
创建显式管道以发送和检索消息。例如,创建一个名为
ORDER_PIPE的管道。DECLARE r_status INTEGER; BEGIN r_status := DBMS_PIPE.CREATE_PIPE(pipename => 'ORDER_PIPE'); END; /有关更多信息,请参见 CREATE_PIPE Function 。
-
检验是否创建了管道。
SELECT ownerid, name, type FROM v$db_pipes WHERE name = 'ORDER_PIPE';OWNERID NAME TYPE ------- ---------- ------- 80 ORDER_PIPE PRIVATE -
使用
DBMS_PIPE过程设置默认访问身份证明和位置 URI,以将持久性消息存储到云对象存储。BEGIN DBMS_PIPE.SET_CREDENTIAL_NAME('my_persistent_pipe_cred'); DBMS_PIPE.SET_LOCATION_URI('https://objectstorage.us-phoenix-1.oraclecloud.com/n/namespace-string/b/bucketname1/'); END; /这些过程设置用于
DBMS_PIPE过程的缺省身份证明名称和缺省位置 URI。如果您使用 Oracle Cloud Infrastructure Object Storage 来存储消息,则可以使用 Oracle Cloud Infrastructure Native URI 或 Swift URI。但是,位置 URI 和身份证明在类型中必须匹配,如下所示:
-
如果您使用本机 URI 格式来访问 Oracle Cloud Infrastructure Object Storage,则必须在身份证明对象中使用本机 Oracle Cloud Infrastructure 签名密钥验证。
-
如果使用 Swift URI 格式访问 Oracle Cloud Infrastructure Object Storage,则必须在身份证明对象中使用验证令牌验证。
有关更多信息,请参见 SET_CREDENTIAL_NAME Procedure 和 GET_LOCATION_URI Function 。
-
-
在管道上打包并发送消息。
DECLARE l_result INTEGER; l_date DATE; BEGIN l_date := sysdate; DBMS_PIPE.PACK_MESSAGE(l_date); -- date of order DBMS_PIPE.PACK_MESSAGE('C123'); -- order number DBMS_PIPE.PACK_MESSAGE(5); -- number of items in order DBMS_PIPE.PACK_MESSAGE('Printers'); -- type of item in order l_result := DBMS_PIPE.SEND_MESSAGE( pipename => 'ORDER_PIPE', credential_name => DBMS_PIPE.GET_CREDENTIAL_NAME, location_uri => DBMS_PIPE.GET_LOCATION_URI); IF l_result = 0 THEN DBMS_OUTPUT.put_line('DBMS_PIPE sent order successfully'); END IF; END; /有关详细信息,请参阅 Oracle Database 19c PL/SQL Packages and Types Reference 或 Oracle Database 26ai PL/SQL Packages and Types Reference 和 SEND_MESSAGE Function 中的 PACK_MESSAGE Procedures 。
在同一数据库上检索持久消息
介绍从同一自治 AI 数据库实例(发送消息的实例)上的显式管道检索持久性消息的步骤。
在自治 AI 数据库实例上,您可以从其他会话接收发送到管道的消息。DBMS_PIPE 过程是调用的权限过程,并以当前调用的用户的身份运行。
专用管道由创建管道的当前用户拥有。专用管道只能由创建管道的同一用户访问。这适用于使用内存中消息的管道以及使用持久性消息传送来处理存储在云对象存储中的消息的管道。
对 DBMS_PIPE 具有执行权限的任何数据库会话都可以访问公共管道。这适用于使用内存中消息的管道以及使用持久性消息传送来处理存储在云对象存储中的消息的管道。
-
检验是否创建了管道。
SELECT ownerid, name, type FROM v$db_pipes WHERE name = 'ORDER_PIPE';OWNERID NAME TYPE ------- ---------- ------- 80 ORDER_PIPE PRIVATE如果您位于同一自治 AI 数据库实例上并且存在管道,则无需在收到消息之前运行
DBMS_PIPE.CREATE_PIPE。这适用于在同一实例上创建管道的情况,如 Create an Explicit Persistent Pipe and Send a Message 中所示。 -
从管道接收消息。
DECLARE message1 DATE; message2 VARCHAR2(100); message3 INTEGER; message4 VARCHAR2(100); l_result INTEGER; BEGIN DBMS_PIPE.SET_CREDENTIAL_NAME('my_persistent_pipe_cred'); DBMS_PIPE.SET_LOCATION_URI('https://objectstorage.us-phoenix-1.oraclecloud.com/n/namespace-string/b/bucketname1/'); l_result := DBMS_PIPE.RECEIVE_MESSAGE ( pipename => 'ORDER_PIPE', timeout => DBMS_PIPE.MAXWAIT, credential_name => DBMS_PIPE.GET_CREDENTIAL_NAME, location_uri => DBMS_PIPE.GET_LOCATION_URI); IF l_result = 0 THEN DBMS_PIPE.unpack_message(message1); DBMS_PIPE.unpack_message(message2); DBMS_PIPE.unpack_message(message3); DBMS_PIPE.unpack_message(message4); DBMS_OUTPUT.put_line('Order Received Successfully On: ' || TO_CHAR(sysdate, 'dd-mm-yyyy hh24:mi:ss')); DBMS_OUTPUT.put_line('Date of Order: ' || message1); DBMS_OUTPUT.put_line('Order Number: ' || message2); DBMS_OUTPUT.put_line('Number of Items In Order: ' || message3); DBMS_OUTPUT.put_line('Item Type in Order: ' || message4); END IF; END; /当您在同一自治 AI 数据库实例上时,身份证明已存在,您无需运行
DBMS_CLOUD.CREATE_CREDENTIAL即可接收消息。这适用于在同一实例上创建管道的情况,如 Create an Explicit Persistent Pipe and Send a Message 中所示。
有关更多信息,请参见 SET_CREDENTIAL_NAME Procedure 和 GET_LOCATION_URI Function 。
有关更多信息,请参见 RECEIVE_MESSAGE Function 。
通过在其他数据库上创建管道来检索持久消息
介绍检索云对象存储中存储的持久性消息的步骤,该持久性消息使用与发送消息的实例不同的自治 AI 数据库实例的显式管道。
-
使用过程
DBMS_CLOUD.CREATE_CREDENTIAL存储对象存储身份证明。例如:BEGIN DBMS_CLOUD.CREATE_CREDENTIAL( credential_name => 'my_persistent_pipe_cred', username => 'adb_user@example.com', password => 'password' ); END; /此操作以加密格式将身份证明存储在数据库中。可以将任何名称用于身份证明名称。请注意,除非对象存储身份证明发生更改,否则此步骤仅需要一次。存储身份证明后,您可以使用相同的身份证明名称访问云对象存储以使用
DBMS_PIPE发送和接收消息。有关参数的详细信息,请参见 CREATE_CREDENTIAL Procedure 。
注:一些工具(如 SQL*Plus 和 SQL Developer)使用 & 符号 (
&) 作为特殊字符。如果口令中有 & 符号,请使用示例中所示工具中的SET DEFINE OFF命令禁用特殊字符并正确创建身份证明。 -
创建一个与发送消息的管道同名的显式管道。例如,创建一个名为
ORDER_PIPE的管道。DECLARE r_status INTEGER; BEGIN r_status := DBMS_PIPE.CREATE_PIPE(pipename => 'ORDER_PIPE'); END; /请参见 CREATE_PIPE Function 。
-
检验是否创建了管道。
SELECT ownerid, name, type FROM v$db_pipes WHERE name = 'ORDER_PIPE';OWNERID NAME TYPE ------- ---------- ------- 80 ORDER_PIPE PRIVATE -
使用
DBMS_PIPE过程为对象存储设置默认访问身份证明和位置 URI,以便DBMS_PIPE可以访问持久性消息。BEGIN DBMS_PIPE.SET_CREDENTIAL_NAME('my_persistent_pipe_cred'); DBMS_PIPE.SET_LOCATION_URI('https://objectstorage.us-phoenix-1.oraclecloud.com/n/namespace-string/b/bucketname1/'); END; /这些过程设置用于
DBMS_PIPE过程的缺省身份证明名称和缺省位置 URI。如果您使用 Oracle Cloud Infrastructure Object Storage 来存储消息,则可以使用 Oracle Cloud Infrastructure Native URI 或 Swift URI。但是,位置 URI 和身份证明在类型中必须匹配,如下所示:
-
如果您使用本机 URI 格式来访问 Oracle Cloud Infrastructure Object Storage,则必须在身份证明对象中使用本机 Oracle Cloud Infrastructure 签名密钥验证。
-
如果使用 Swift URI 格式访问 Oracle Cloud Infrastructure Object Storage,则必须在身份证明对象中使用验证令牌验证。
有关更多信息,请参见 SET_CREDENTIAL_NAME Procedure 和 GET_LOCATION_URI Function 。
-
-
从持久性管道接收消息。
DECLARE message1 DATE; message2 VARCHAR2(100); message3 INTEGER; message4 VARCHAR2(100); l_result INTEGER; BEGIN DBMS_PIPE.SET_CREDENTIAL_NAME('my_persistent_pipe_cred'); DBMS_PIPE.SET_LOCATION_URI('https://objectstorage.us-phoenix-1.oraclecloud.com/n/namespace-string/b/bucketname1/'); l_result := DBMS_PIPE.RECEIVE_MESSAGE ( pipename => 'ORDER_PIPE', timeout => DBMS_PIPE.MAXWAIT, credential_name => DBMS_PIPE.GET_CREDENTIAL_NAME, location_uri => DBMS_PIPE.GET_LOCATION_URI); IF l_result = 0 THEN DBMS_PIPE.unpack_message(message1); DBMS_PIPE.unpack_message(message2); DBMS_PIPE.unpack_message(message3); DBMS_PIPE.unpack_message(message4); DBMS_OUTPUT.put_line('Order Received Successfully On: ' || TO_CHAR(sysdate, 'dd-mm-yyyy hh24:mi:ss')); DBMS_OUTPUT.put_line('Date of Order: ' || message1); DBMS_OUTPUT.put_line('Order Number: ' || message2); DBMS_OUTPUT.put_line('Number of Items In Order: ' || message3); DBMS_OUTPUT.put_line('Item Type in Order: ' || message4); END IF; END; /有关更多信息,请参见 RECEIVE_MESSAGE Function 。
删除持久性管道
描述删除持久性管道的步骤。
持久管道通过在云对象存储中存储消息来发送和接收消息。使用 DBMS_PIPE.REMOVE_PIPE 删除自治 AI 数据库实例上的持久性管道。
-
调用
DBMS_PIPE.REMOVE_PIPE函数以删除管道。DECLARE l_result INTEGER; BEGIN l_result := DBMS_PIPE.REMOVE_PIPE('ORDER_PIPE'); END; /REMOVE_PIPE函数从运行该管道的自治 AI 数据库实例中删除管道,但是REMOVE_PIPE不会影响具有使用相同位置 URI 的相同名称管道的其他自治 AI 数据库实例。 -
在您运行
DBMS_PIPE.REMOVE_PIPE的自治 AI 数据库实例上,验证是否已删除管道。SELECT ownerid, name, type FROM v$db_pipes WHERE name = 'ORDER_PIPE';No rows selected