Armazenar Mensagens em Cache com Pipes Singleton

Singleton Pipe é uma adição ao pacote DBMS_PIPE que permite armazenar em cache e recuperar uma mensagem personalizada e compartilhar a mensagem em várias sessões de banco de dados com leituras simultâneas.

Sobre o Armazenamento em Cache de Mensagens com Pipes Singleton

O pacote DBMS_PIPE tem funcionalidade estendida no Autonomous Database para suportar Pipes Singleton.

Um tubo Singleton em DBMS_PIPE:

  • Fornece armazenamento em cache na memória de dados personalizados usando mensagens Singleton Pipe.

  • Suporta a capacidade de armazenar em cache e recuperar uma mensagem personalizada de até 32.767 bytes.

  • Suporta o compartilhamento de uma mensagem em cache em várias sessões de banco de dados com leituras simultâneas. Isso fornece alto throughput e suporta leituras simultâneas de mensagens entre sessões de banco de dados.

  • Suporta bancos de dados Somente para Leitura e Leitura/Gravação.

  • Suporta vários métodos de invalidação de cache:

    • Invalidação de cache explícita controlada pelo usuário.
    • Invalidação de cache após um intervalo de tempo especificado pelo usuário (em segundos). Esse método de invalidação é controlado pelo remetente da mensagem, usando o parâmetro shelflife, em vez de pelos leitores de mensagem. Isso evita as armadilhas comuns devido ao uso incorreto do cache pelos leitores.

Sobre Tubos Padrão e Tubos Singleton

O Pacote DBMS_PIPE permite que duas ou mais sessões de banco de dados se comuniquem usando mensagens na memória. A funcionalidade Pipe tem vários aplicativos, como interface de serviço externo, depuração, transações independentes e alertas. Consulte DBMS_PIPE em Oracle Database 19c PL/SQL Packages and Types Reference ou Oracle Database 23ai PL/SQL Packages and Types Reference para obter mais informações.

A seguir, descrição de database-pipe-messages-singleton-pipes.eps
Descrição da ilustração database-pipe-messages-singleton-pipes.eps

Um Singleton Pipe pode ser qualquer um dos tipos DBMS_PIPE suportados:

  • Tubo Implícito: Criado automaticamente quando uma mensagem é enviada com um nome de pipe desconhecido usando a função DBMS_PIPE.SEND_MESSAGE.
  • Tubo Explícito: Criado usando a função DBMS_PIPE.CREATE_PIPE com um nome de pipe especificado pelo usuário.
  • Tubo Público: Acessível por qualquer usuário com permissão EXECUTE no pacote DBMS_PIPE.
  • Pipe Privado: Acessível por sessões com o mesmo usuário que o criador do pipe.

Os Pipes Singleton fornecem a capacidade de armazenar em cache uma única mensagem na memória da instância do Autonomous Database.

A seguir, mostra o workflow geral para usar pipes singleton.

A seguir, descrição de singleton-pipe-workflow.eps
Descrição da ilustração singleton-pipe-workflow.eps

Visão geral e recursos do Singleton Pipe

  • Mensagens Únicas

    • Um Singleton Pipe pode armazenar em cache uma mensagem no pipe, daí o nome "singleton".
    • A mensagem em um Singleton Pipe pode ser composta por vários campos, até um tamanho total de mensagem de 32.767 bytes.
    • DBMS_PIPE suporta a capacidade de compactar vários atributos em uma mensagem usando o procedimento DBMS_PIPE.PACK_MESSAGE.
    • Para um Pipe Único Público, a mensagem pode ser recebida por qualquer sessão de banco de dados com privilégio de execução no pacote DBMS_PIPE.
    • Para o Private Singleton Pipe, a mensagem pode ser recebida por sessões com o mesmo usuário que o criador do Singleton Pipe.
  • Alto Throughput de Mensagens para Leituras
    • Os Pipes Singleton armazenam em cache a mensagem no pipe até que ela seja invalidada ou expurgada. As sessões do banco de dados podem ler simultaneamente uma mensagem do Singleton Pipe.
    • Receber uma mensagem de um tubo Singleton é uma operação sem bloqueio.
  • Cache de Mensagem
    • Uma mensagem é armazenada em cache em um Singleton Pipe usando DBMS_PIPE.SEND_MESSAGE.
    • Se houver uma mensagem em cache existente no Singleton Pipe, DBMS_PIPE.SEND_MESSAGE substituirá a mensagem anterior para manter apenas uma mensagem no Singleton Pipe.
  • Invalidação de Mensagem
    • Invalidação Explícita: expurga o pipe com o procedimento DBMS_PIPE.PURGE ou substituindo a mensagem por DBMS_PIPE.SEND_MESSAGE.
    • Invalidação Automática: uma mensagem pode ser invalidada automaticamente após o tempo especificado de shelflife.
  • Sem Remoção da Memória do Banco de Dados
    • Os Pipes Singleton não são despejados da memória do Oracle Database.
    • Um Pipe Singleton Explícito continua a residir na memória do banco de dados até ser removido usando DBMS_PIPE.REMOVE_PIPE ou até que o banco de dados seja reiniciado.
    • Um Singleton Pipe Implícito permanece na memória do banco de dados até que haja uma mensagem em cache no pipe.

Operações de tubulação Singleton

Operação DBMS_PIPE Função ou Procedimento

Criar um Pipe Singleton Explícito

Função CREATE_PIPE

Armazenar em cache uma mensagem no Singleton Pipe

PACK_MESSAGE Procedures em Oracle Database 19c PL/SQL Packages and Types Reference ou Oracle Database 23ai PL/SQL Packages and Types Reference

Função SEND_MESSAGE

Ler uma mensagem em cache do Singleton Pipe

RECIEVE_MESSAGE Function, UNPACK_MESSAGE Procedures em Oracle Database 19c PL/SQL Packages and Types Reference ou Oracle Database 23ai PL/SQL Packages and Types Reference

Excluir uma mensagem no Singleton Pipe

Procedimento PURGE em Oracle Database 19c Pacotes PL/SQL e Referência de Tipos ou Oracle Database 23ai Pacotes PL/SQL e Referência de Tipos

Remover um Tubo Simples Explícito

REMOVE_PIPE Function em Oracle Database 19c PL/SQL Packages and Types Reference ou Oracle Database 23ai PL/SQL Packages and Types Reference

Atualização Automática de Mensagem Armazenada em Cache com uma Função de Cache

O pacote DBMS_PIPE permite preencher automaticamente uma mensagem Singleton Pipe usando uma função de cache definida pelo usuário.

Por padrão, depois que uma mensagem é invalidada com a invalidação explícita ou implícita do Singleton Pipe, um DBMS_PIPE.RECEIVE_MESSAGE subsequente não resulta no recebimento de nenhuma mensagem. Para adicionar uma nova mensagem ao pipe, a mensagem deve ser armazenada no cache explicitamente chamando DBMS_PIPE.SEND_MESSAGE. Para evitar esse caso, onde nenhuma mensagem está disponível quando você lê em um Singleton Pipe, você pode definir uma função de cache. Com uma função de cache definida, a função de cache é chamada automaticamente quando você recebe uma mensagem nos seguintes cenários:

  • Quando o tubo Singleton estiver vazio.
  • Quando a mensagem em um Singleton Pipe é inválida devido ao tempo decorrido de shelflife.

Para usar uma função de cache, defina a função de cache e inclua o parâmetro cache_func com DBMS_PIPE.RECEIVE_MESSAGE. Uma função de cache definida pelo usuário fornece o seguinte:

  • A função de cache pode ser especificada ao ler uma mensagem de um Singleton Pipe usando DBMS_PIPE.RECEIVE_MESSAGE.
  • Quando não há mensagem no Singleton Pipe, DBMS_PIPE.RECEIVE_MESSAGE chama a função de cache.
  • Quando o tempo da mensagem shelflife tiver decorrido, o banco de dados preencherá automaticamente uma nova mensagem no Singleton Pipe.

O uso de uma função de cache simplifica o trabalho com Pipes Singleton. Não é necessário tratar casos de falha para receber uma mensagem de um pipe vazio. Além disso, uma função de cache garante que não haja falta de cache quando você lê mensagens de um Singleton Pipe, fornecendo o uso máximo da mensagem em cache.

A seguir, descrição de automatic-cache-refresh-cache-function.eps
Descrição da ilustração automatic-cache-refresh-cache-function.eps

Quando você define uma função de cache, o nome da função deve ser totalmente qualificado com o esquema do proprietário:

  • OWNER.FUNCTION_NAME
  • OWNER.PACKAGE.FUNCTION_NAME

Defina uma função de cache com a seguinte assinatura:

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

As operações típicas dentro de uma função de cache são:

  • Crie um Pipe Singleton, para um Pipe Explícito, usando DBMS_PIPE.CREATE_PIPE.
  • Crie uma mensagem para armazenar em cache no Singleton Pipe.
  • Envie a mensagem para o pipe especificado na função de cache, opcionalmente especificando um shelflife para a mensagem implícita.

Para usar uma função de cache, o usuário da sessão atual que chama DBMS_PIPE.RECEIVE_MESSAGE deve ter os privilégios necessários para executar a função de cache.

Consulte Função RECIEVE_MESSAGE para obter mais informações sobre como definir uma função de cache.

Criar um Pipe Singleton Explícito

Descreve as etapas para criar um Pipe Singleton com um nome de pipe especificado (um Pipe Singleton Explícito).

Primeiro, para este exemplo, crie a função auxiliar receive_message para chamar repetidamente DBMS_PIPE.RECEIVE_MESSAGE. Isso permite testar a funcionalidade de pipe singleton.

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. Crie um pipe singleton explícito chamado PIPE_TEST com o parâmetro shelflife definido como 3600 (segundos).
    DECLARE
      l_status INTEGER;
    BEGIN
      l_status := DBMS_PIPE.CREATE_PIPE(
                    pipename => 'MY_PIPE1',
                    private => TRUE,
                    singleton => TRUE,
                    shelflife => 3600);
    END;
    /

    Consulte Função CREATE_PIPE para obter mais informações.

  2. Verifique se o pipe singleton foi criado.
    SELECT name, singleton, type
         FROM v$db_pipes WHERE name= '&pipename' ORDER BY 1;
    
    NAME                 SINGLETON  TYPE
    -------------------- ---------- -------
    PIPE_TEST            YES        PRIVATE
  3. Empacote e envie uma mensagem no pipe singleton.
    
    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
  4. Receba uma mensagem de um pipe singleton.
    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

    A função receive_message é uma função auxiliar que chama DBMS_PIPE.RECEIVE_MESSAGE.

  5. Limpe a mensagem e remova o pipe.
    EXEC DBMS_PIPE.PURGE('&pipename');
    SELECT DBMS_PIPE.REMOVE_PIPE('&pipename') status FROM DUAL;

Criar um Pipe Singleton Explícito com uma Função de Cache

Descreve as etapas para criar um Pipe Singleton com um nome de pipe especificado, um Pipe Singleton Explícito e fornece uma função de cache. Uma função de cache permite preencher automaticamente a mensagem em um pipe singleton.

  1. Crie uma função de cache, test_cache_message para um pipe singleton.
    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;
    /

    Observação:

    O usuário da sessão atual que chama DBMS_PIPE.RECEIVE_MESSAGE deve ter o privilégio necessário para executar a função de cache.
  2. Receba com uma função de cache e confirme se a mensagem é preenchida no pipe. O pipe deve existir como um pipe privado criado na função de cache.
    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
    

    A função receive_message é uma função auxiliar que chama DBMS_PIPE.RECEIVE_MESSAGE. Consulte Criar um Pipe Singleton Explícito para obter a definição receive_message.

    Consulte Função CREATE_PIPE para obter mais informações.

  3. Receba sem a função de cache para confirmar se a mensagem persiste no pipe.
    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

    A função receive_message é uma função auxiliar que chama DBMS_PIPE.RECEIVE_MESSAGE. Consulte Criar um Pipe Singleton Explícito para obter a definição receive_message.

    Consulte Função CREATE_PIPE para obter mais informações.