將永久訊息與儲存在雲端物件存放區中的訊息搭配使用

DBMS_PIPE 套件在 Autonomous Database 上具有擴充功能,可支援訊息儲存在雲端物件存放區中的持續性訊息傳遞。

關於與 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.eps 的描述如下
database-pipe-persistent-messaging.eps 圖解描述

使用 DBMS_PIPE 的現有應用程式可在最少的變更下繼續作業。您可以使用登入觸發程式或使用其他初始化常式,設定使用 DBMS_PIPE 搭配證明資料物件和位置 URI 的現有應用程式。設定 DBMS_PIPE 證明資料和位置 URI 之後,不需要進行其他變更即可使用永久訊息。管道的所有後續使用都會將訊息儲存在雲端物件存放區,而不是儲存在資料庫記憶體中。這可讓您在進行最少的變更時,將記憶體內的訊息儲存體方法變更為永久的雲端物件儲存體。

永久訊息簡介與功能

使用永久訊息的 DBMS_PIPE 功能:

  • 可以在相同區域或跨區域的多個 Autonomous Database 執行處理之間傳送和擷取訊息。

  • 持續性訊息保證只能由一個程序寫入或讀取。這可避免因並行讀取和寫入而導致訊息內容不一致。DBMS_PIPE 僅允許一項作業、傳送訊息或接收訊息到指定時間為作用中,且這些作業受到鎖定機制的保護。不過,如果因進行中的作業而無法執行作業,則程序會定期重試,直到達到 timeout 值為止。

  • DBMS_PIPE 使用 DBMS_CLOUD 來存取雲端物件存放區。訊息可以儲存在任何支援的雲端物件存放區中。如需詳細資訊,請參閱雲端物件儲存 URI 格式

  • DBMS_PIPE 使用 DBMS_CLOUD 來存取「雲端物件存放區」,並且提供所有支援的證明資料類型:

DBMS_PIPE 權限授權與安全性

DBMS_PIPE 程序會以呼叫者的權限執行。專用管道是由目前使用者所擁有,而使用者所建立的專用管道只能由同一使用者使用。這適用於儲存訊息至雲端物件存放區的記憶體內管和永久訊息管道。傳送與接收在呼叫者的綱要中執行的訊息。

使用將訊息儲存至「雲端物件存放區」的專用管道時,必須要有證明資料物件,才能使用由 location_uri 參數識別的雲端物件存放區進行認證。呼叫使用者必須具備使用 credential_name 參數指定之證明資料物件的 EXECUTE 權限,才能存取物件存放區。

若要使用公用管道,使用者 (資料庫階段作業) 必須具備 DBMS_PIPE 的執行權限。對於使用永久訊息並將訊息儲存至「雲端物件存放區」的公用管道,使用者、資料庫階段作業必須具備 DBMS_CLOUD 的執行權限,並且對證明資料物件執行權限 (或者您可以建立可存取包含訊息之位置 URI 的證明資料物件)。

DBMS_PIPE 限制

DBMS_PIPE 套裝軟體不支援在使用不同字元集的資料庫之間傳送訊息。例如,如果您有一個使用 AL32UTF8 的 Autonomous Database 執行處理,以及另一個使用 WE8MSWIN1252 的執行處理,就無法在這兩個資料庫之間傳送含有 DBMS_PIPE 的訊息。在此情況下,如果您嘗試在這兩個資料庫之間傳送含有 DBMS_PIPE 的訊息,系統將會發出錯誤 ORA-12704

請參閱 Character Set Selection for Autonomous Database 以瞭解詳細資訊。

建立明確的永久管線並傳送訊息

描述使用指定管名稱 (明確管) 建立永久管的步驟。

  1. 使用 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 程序。對於 Oracle Cloud Infrastructure Object Storage ,證明資料必須使用原生 Oracle Cloud Infrastructure 認證。

    附註:

    某些工具 (例如 SQL*Plus 和 SQL Developer) 會使用 & 字元 (&) 作為特殊字元。如果您的密碼包含 & 字元,請在這些工具中使用 SET DEFINE OFF 命令 (如範例所示),以停用特殊字元並正確建立證明資料。
  2. 建立明確的管道以傳送與擷取訊息。例如,建立名為 ORDER_PIPE 的管道。
    DECLARE
      r_status INTEGER;
    BEGIN
        r_status := DBMS_PIPE.CREATE_PIPE(pipename => 'ORDER_PIPE');
    END;
    /

    如需詳細資訊,請參閱 CREATE_PIPE 函數

  3. 驗證已建立管道。
    SELECT ownerid, name, type FROM v$db_pipes 
           WHERE name = 'ORDER_PIPE';
    OWNERID NAME       TYPE    
    ------- ---------- ------- 
         80 ORDER_PIPE PRIVATE 
  4. 您可以使用 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 原生 URI 或 Swift URI。但是,位置 URI 與憑證的類型必須相符,如下所示:

    • 如果您使用原生 URI 格式來存取 Oracle Cloud Infrastructure Object Storage ,就必須在證明資料物件中使用原生 Oracle Cloud Infrastructure 簽署金鑰認證。

    • 如果您使用 Swift URI 格式來存取 Oracle Cloud Infrastructure Object Storage ,則必須在證明資料物件中使用認證權杖認證。

    如需詳細資訊,請參閱 SET_CREDENTIAL_NAME 程序GET_LOCATION_URI 函數

  5. 在管道上包裝並傳送訊息。
    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 中的 PACK_MESSAGE ProceduresOracle Database 23ai PL/SQL Packages and Types ReferenceSEND_MESSAGE 函數以瞭解詳細資訊。

擷取相同資料庫的永久訊息

描述從相同 Autonomous Database 例項 (訊息傳送的例項) 上明確管道擷取永久訊息的步驟。

Autonomous Database 例項上,您可以接收從不同階段作業傳送至管道的訊息。DBMS_PIPE 程序是呼叫者的權限程序,並以目前呼叫的使用者身分執行。

專用管道是由建立管道的目前使用者所擁有。專用管道只能由建立管道的相同使用者存取。這適用於使用記憶體內訊息的管道,以及使用永久訊息與儲存在雲端物件存放區中訊息的管道。

具備 DBMS_PIPE 執行權限的任何資料庫階段作業都可以存取公用管道。這適用於使用記憶體內訊息的管道,以及使用永久訊息與儲存在雲端物件存放區中訊息的管道。

  1. 驗證已建立管道。
    SELECT ownerid, name, type FROM v$db_pipes 
           WHERE name = 'ORDER_PIPE';
    
    OWNERID NAME       TYPE    
    ------- ---------- ------- 
         80 ORDER_PIPE PRIVATE 

    當您在相同的 Autonomous Database 例項上且存在管道時,在收到訊息之前,您不需要執行 DBMS_PIPE.CREATE_PIPE。這適用於在相同例證上建立管路時 (如建立明確永久管路並傳送訊息所示)。

  2. 從管道接收訊息。
    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;
    /

    當您在同一個 Autonomous Database 執行處理上時,證明資料已經存在,而且您不需要執行 DBMS_CLOUD.CREATE_CREDENTIAL 即可接收訊息。這適用於在相同例證上建立管路時 (如建立明確永久管路並傳送訊息所示)。

如需詳細資訊,請參閱 SET_CREDENTIAL_NAME 程序GET_LOCATION_URI 函數

如需詳細資訊,請參閱 RECEIVE_MESSAGE 函數

在不同的資料庫上建立管路以擷取永久訊息

描述在 Autonomous Database 執行處理上使用明確管道擷取儲存在雲端物件存放區中之永久訊息的步驟,而此執行處理與傳送訊息的執行處理不同。

  1. 使用 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 程序

    附註:

    某些工具 (例如 SQL*Plus 和 SQL Developer) 會使用 & 字元 (&) 作為特殊字元。如果您的密碼包含 & 字元,請在這些工具中使用 SET DEFINE OFF 命令 (如範例所示),以停用特殊字元並正確建立證明資料。
  2. 建立與傳送訊息之管道具有相同名稱的明確管道。例如,建立名為 ORDER_PIPE 的管道。
    DECLARE
      r_status INTEGER;
    BEGIN
        r_status := DBMS_PIPE.CREATE_PIPE(pipename => 'ORDER_PIPE');
    END;
    /

    請參閱 CREATE_PIPE 函數

  3. 驗證已建立管道。
    SELECT ownerid, name, type FROM v$db_pipes 
           WHERE name = 'ORDER_PIPE';
    
    OWNERID NAME       TYPE    
    ------- ---------- ------- 
         80 ORDER_PIPE PRIVATE 
  4. 使用 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 原生 URI 或 Swift URI。但是,位置 URI 與憑證的類型必須相符,如下所示:

    • 如果您使用原生 URI 格式來存取 Oracle Cloud Infrastructure Object Storage ,就必須在證明資料物件中使用原生 Oracle Cloud Infrastructure 簽署金鑰認證。

    • 如果您使用 Swift URI 格式來存取 Oracle Cloud Infrastructure Object Storage ,則必須在證明資料物件中使用認證權杖認證。

    如需詳細資訊,請參閱 SET_CREDENTIAL_NAME 程序GET_LOCATION_URI 函數

  5. 從永久管道接收訊息。
    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 函數

移除永久管線

描述移除永久管道的步驟。

永久管道會在雲端物件存放區中儲存訊息,以傳送及接收訊息。使用 DBMS_PIPE.REMOVE_PIPE 移除 Autonomous Database 實例上的永久管道。

  1. 呼叫 DBMS_PIPE.REMOVE_PIPE 函數以移除管道。
    DECLARE
       l_result  INTEGER;
    BEGIN
         l_result := DBMS_PIPE.REMOVE_PIPE('ORDER_PIPE');
    END;
    /

    REMOVE_PIPE 函數會從執行管路的 Autonomous Database 例項中移除管路,但是 REMOVE_PIPE 不會影響其他具有使用相同位置 URI 之管路的 Autonomous Database 例項。

  2. Autonomous Database 實例上執行 DBMS_PIPE.REMOVE_PIPE,確認已移除該管道。
    SELECT ownerid, name, type FROM v$db_pipes 
           WHERE name = 'ORDER_PIPE';
    
    No rows selected