含有單一管線的快取訊息

Singleton Pipe 是 DBMS_PIPE 套裝程式的新增功能,可讓您快取和擷取自訂訊息,並透過並行讀取跨多個資料庫階段作業共用訊息。

關於使用單一管路快取訊息

DBMS_PIPE 套裝軟體在 Autonomous Database 上具有擴充功能,可支援單一管道。

DBMS_PIPE 中的單一管:

  • 使用單一管路訊息提供自訂資料的記憶體內快取。

  • 支援快取和擷取最多 32,767 個位元組的自訂訊息。

  • 支援透過並行讀取跨多個資料庫階段作業共用快取訊息。這可提供高傳輸量,並支援跨資料庫階段作業並行讀取訊息。

  • 支援唯讀和讀寫資料庫。

  • 支援數種快取無效化方法:

    • 由使用者控制的明確快取無效化。
    • 使用者指定的時間間隔之後的快取無效化 (秒)。此無效驗證方法是由訊息寄件者所控制,使用 shelflife 參數,而非由訊息讀取者所控制。這可避免常見的陷阱,因為讀取器使用快取不正確。

關於標準管和單孔管

DBMS_PIPE 套裝程式允許兩個或多個資料庫階段作業使用記憶體內訊息進行通訊。管線功能有數個應用程式,例如外部服務介面、除錯、獨立交易和警示。請參閱 Oracle Database 19c PL/SQL Packages and Types Reference 中的 DBMS_PIPEOracle Database 23ai PL/SQL Packages and Types Reference ,瞭解詳細資訊。

database-pipe-messages-singleton-pipes.eps 的描述如下
database-pipe-messages-singleton-pipes.eps 圖解描述

Singleton Pipe 可以是任何支援的 DBMS_PIPE 類型:

  • 隱含管:使用 DBMS_PIPE.SEND_MESSAGE 函數以不明的管路名稱傳送訊息時,會自動建立訊息。
  • 明確管線:使用 DBMS_PIPE.CREATE_PIPE 函數與使用者指定的管線名稱建立。
  • 公用管道:任何具備 DBMS_PIPE 套裝軟體 EXECUTE 權限的使用者均可存取。
  • 私人管道:具有與管道建立者相同之使用者的階段作業可存取。

Singleton Pipes 可讓您在 Autonomous Database 執行處理的記憶體中快取單一訊息。

以下顯示使用單一管道的一般工作流程。

singleton-pipe-workflow.eps 的描述如下
singleton-pipe-workflow.eps 圖解描述

單一管概觀和功能

  • 單一訊息

    • Singleton Pipe 可在管道中快取一則訊息,因此名稱為 "singleton"。
    • Singleton Pipe 中的訊息可由多個欄位組成,總訊息大小為 32,767 個位元組。
    • DBMS_PIPE 支援使用 DBMS_PIPE.PACK_MESSAGE 程序將多個屬性封裝在訊息中。
    • 對於公用單一管路,任何具備 DBMS_PIPE 套裝程式執行權限的資料庫階段作業都可以接收訊息。
    • 若為「專用單一管」,階段作業可以接收與「單一管」建立者相同之使用者的訊息。
  • 讀取的訊息處理量上限
    • Singleton Pipes 會將訊息快取到管中,直到該訊息失效或被清除為止。資料庫階段作業可以並行從 Singleton Pipe 讀取訊息。
    • 從 Singleton Pipe 接收訊息是一項無阻塞的作業。
  • 訊息快取
    • 使用 DBMS_PIPE.SEND_MESSAGE 在單一管中快取訊息。
    • 如果 Singleton Pipe 中有現有的快取訊息,則 DBMS_PIPE.SEND_MESSAGE 會覆寫先前的訊息,以便只在 Singleton Pipe 中保留一則訊息。
  • 訊息無效
    • 明確無效驗證:使用 DBMS_PIPE.PURGE 程序清除管道,或使用 DBMS_PIPE.SEND_MESSAGE 覆寫訊息。
    • 自動無效驗證:訊息可以在指定的 shelflife 時間過後自動失效。
  • 資料庫記憶體沒有收回
    • Singleton Pipes 不會從 Oracle Database 記憶體收回。
    • 明確的 Singleton Pipe 會繼續位於資料庫記憶體中,直到使用 DBMS_PIPE.REMOVE_PIPE 移除為止,或重新啟動資料庫為止。
    • 「隱含單一管」會保留在資料庫記憶體中,直到管中有一個快取訊息為止。

單一管路作業

操作 DBMS_PIPE 函數或程序

建立明確的單一管路

CREATE_PIPE 函數

在 Singleton Pipe 中快取訊息

PACK_MESSAGE Procedures in Oracle Database 19c PL/SQL Packages and Types Reference or Oracle Database 23ai PL/SQL Packages and Types Reference

SEND_MESSAGE 函數

從 Singleton Pipe 讀取快取訊息

RECIEVE_MESSAGE 函數 UNPACK_MESSAGE 程序,位於 Oracle Database 19c PL/SQL Packages and Types ReferenceOracle Database 23ai PL/SQL Packages and Types Reference

刪除 Singleton Pipe 中的訊息

Oracle Database 19c PL/SQL Packages and Types ReferenceOracle Database 23ai PL/SQL Packages and Types Reference 中的 PURGE 程序

移除明確的單一管路

REMOVE_PIPE Function in Oracle Database 19c PL/SQL Packages and Types Reference or Oracle Database 23ai PL/SQL Packages and Types Reference

使用快取功能自動重新整理快取訊息

DBMS_PIPE 套裝程式可讓您使用使用者定義的快取函數自動填入「單一管線」訊息。

依照預設,當訊息因「單一管」明確或隱含無效驗證而失效之後,後續的 DBMS_PIPE.RECEIVE_MESSAGE 將不會收到任何訊息。若要新增訊息至管道,必須透過呼叫 DBMS_PIPE.SEND_MESSAGE 明確快取訊息。若要避免此情況,當您從「單一管」讀取時沒有可用的訊息,可以定義快取函數。定義快取函數後,當您收到下列情況的訊息時,會自動呼叫快取函數:

  • Singleton Pipe 是空的。
  • 當 Singleton Pipe 中的訊息因為經過 shelflife 時間而無效時。

若要使用快取函數,請定義快取函數並包含 cache_func 參數與 DBMS_PIPE.RECEIVE_MESSAGE。使用者定義的快取函數提供下列各項:

  • 使用 DBMS_PIPE.RECEIVE_MESSAGE 從單一管路讀取訊息時,可以指定快取函數。
  • 當單一管中沒有訊息時,DBMS_PIPE.RECEIVE_MESSAGE 會呼叫快取函數。
  • 訊息 shelflife 時間過後,資料庫會自動在「單一管線」中填入新訊息。

使用快取函數可簡化單一管的使用。您不需要處理從空管道接收訊息的失敗案例。此外,快取功能可確保從單一管路讀取訊息時不會遺漏快取記憶體,以最大限度地使用快取訊息。

auto-cache-refresh-cache-function.eps 的描述如下
auto-cache-refresh-cache-function.eps 圖解描述

當您定義快取函數時,函數名稱必須完全符合擁有者綱要:

  • OWNER.FUNCTION_NAME
  • OWNER.PACKAGE.FUNCTION_NAME

定義具有下列簽章的快取函數:

CREATE OR REPLACE FUNCTION cache_function_name(
       pipename  IN VARCHAR2
) RETURN INTEGER;

快取函數內的一般作業為:

  • 使用 DBMS_PIPE.CREATE_PIPE 建立明確管的單一管。
  • 建立要在單一管中快取的訊息。
  • 將訊息傳送至快取函數中指定的管道,選擇性地為隱含訊息指定 shelflife

若要使用快取函數,呼叫 DBMS_PIPE.RECEIVE_MESSAGE 的目前階段作業使用者必須具有執行快取函數的必要權限。

請參閱 RECIEVE_MESSAGE 函數,瞭解有關定義快取函數的詳細資訊。

建立明確的單一管路

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

首先,在此範例中,請建立 receive_message 協助程式函數來重複呼叫 DBMS_PIPE.RECEIVE_MESSAGE。這可讓您測試單一管路功能。

CREATE OR REPLACE FUNCTION msg_types AS
       TYPE t_rcv_row IS RECORD (c1 VARCHAR2(32767), c2 NUMBER);
       TYPE t_rcv_tab IS TABLE OF t_rcv_row;
END;


CREATE OR REPLACE FUNCTION receive_message(
      pipename    IN VARCHAR2,
      rcv_count   IN NUMBER DEFAULT 1,
      cache_func  IN VARCHAR2 DEFAULT NULL)
   RETURN msg_types.t_rcv_tab pipelined
    AS
       l_msg    VARCHAR2(32767);
       l_status NUMBER;
 BEGIN
      FOR i IN 1..rcv_count LOOP
           l_status := DBMS_PIPE.RECEIVE_MESSAGE(
            pipename   => pipename,
            cache_func => cache_func,
            timeout    => 1);
         IF l_status != 0 THEN
              raise_application_error(-20000,
             'Message not received for attempt: ' || to_char(i) || ' status: ' ||
            l_status);
         END IF;

         DBMS_PIPE.UNPACK_MESSAGE(l_msg);
             pipe row(msg_types.t_rcv_row(l_msg));
     END LOOP;
 RETURN;
 END;
  1. 建立名為 PIPE_TEST 的明確單一管道,並將 shelflife 參數設為 3600 (秒)。
    DECLARE
      l_status INTEGER;
    BEGIN
      l_status := DBMS_PIPE.CREATE_PIPE(
                    pipename => 'MY_PIPE1',
                    private => TRUE,
                    singleton => TRUE,
                    shelflife => 3600);
    END;
    /

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

  2. 確認已建立單一管路。
    SELECT name, singleton, type
         FROM v$db_pipes WHERE name= '&pipename' ORDER BY 1;
    
    NAME                 SINGLETON  TYPE
    -------------------- ---------- -------
    PIPE_TEST            YES        PRIVATE
  3. 在單一管道包裝並傳送訊息。
    
    EXEC DBMS_PIPE.PACK_MESSAGE('This is a real message that you can get multiple times');
    
    SELECT DBMS_PIPE.SEND_MESSAGE(pipename => '&pipename') status FROM DUAL;
    
    STATUS
    ----------
    0

    請參閱 Oracle Database 19c PL/SQL Packages and Types Reference 中的 PACK_MESSAGE ProceduresOracle Database 23ai PL/SQL Packages and Types ReferenceSEND_MESSAGE 函數以瞭解詳細資訊。

  4. 從單一管道接收訊息。
    SELECT * FROM receive_message(
        pipename => '&pipename',
        rcv_count => 2);
    
    MESSAGE
    --------------------------------------------------------------------------------
    This is a real message that you can get multiple times
    This is a real message that you can get multiple times

    receive_message 函數是呼叫 DBMS_PIPE.RECEIVE_MESSAGE 的協助程式函數。

  5. 清除訊息並移除管道。
    EXEC DBMS_PIPE.PURGE('&pipename');
    SELECT DBMS_PIPE.REMOVE_PIPE('&pipename') status FROM DUAL;

使用快取函數建立明確的單一管路

描述使用指定的管名、明確的單一管建立單一管,並提供快取函數的步驟。快取函數可讓您自動將訊息填入單一管道。

  1. 建立單一管路的快取函數 test_cache_message
    CREATE OR REPLACE FUNCTION test_cache_message(
         pipename IN VARCHAR2) return NUMBER 
    AS 
       l_status NUMBER;
       l_data VARCHAR2(4000);
    BEGIN
       l_status := DBMS_PIPE.CREATE_PIPE(
              pipename => pipename,
              private => TRUE,
              singleton => true,
              shelflife => 600);
       IF l_status != 0 THEN RETURN l_status;
       END IF;
     
       DBMS_PIPE.PACK_MESSAGE('This is a placeholder cache message for an empty pipe');
       l_status := DBMS_PIPE.SEND_MESSAGE(pipename => pipename);
       RETURN l_status;
     END;
    /

    附註:

    呼叫 DBMS_PIPE.RECEIVE_MESSAGE 的目前階段作業使用者必須具備執行快取函數所需的權限。
  2. 接收快取函數並確認訊息會填入 pipe。在快取函數中,管線必須以私密管道的形式存在。
    SELECT * FROM receive_message(
         pipename => '&pipename',
         rcv_count => 1,
         cache_func => 'TEST_CACHE_MESSAGE');
    
    MESSAGE
    ---------------
    This is a placeholder cache message for an empty pipe
    

    receive_message 函數是呼叫 DBMS_PIPE.RECEIVE_MESSAGE 的協助程式函數。請參閱建立明確的單一管,瞭解 receive_message 定義。

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

  3. 不使用快取功能接收,以確認訊息持續存在於管道中。
    SELECT * FROM receive_message(
         pipename => '&pipename',
         rcv_count => 2);
    
    MESSAGE
    ---------------
    This is a placeholder cache message for an empty pipe
    This is a placeholder cache message for an empty pipe

    receive_message 函數是呼叫 DBMS_PIPE.RECEIVE_MESSAGE 的協助程式函數。請參閱建立明確的單一管,瞭解 receive_message 定義。

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