Armazenar Mensagens em Cache em Pipes Singleton

O 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 do banco de dados com leituras simultâneas.

Sobre o Cache de Mensagens com Pipes Singleton

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

Um Singleton Pipe 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 do banco de dados com leituras simultâneas. Isso fornece alto throughput e suporta leituras simultâneas de mensagens entre sessões do banco de dados.

  • Suporta bancos de dados Somente Leitura e 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.

Veja a seguir a descrição da ilustração database-pipe-messages-singleton-pipes.eps
Descrição da ilustração database-pipe-messages-singleton-pipes.eps

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

  • Tubulação Implícita: Criada automaticamente quando uma mensagem é enviada com um nome de pipe desconhecido usando a função DBMS_PIPE.SEND_MESSAGE.
  • Tubulação Explícita: Criada usando a função DBMS_PIPE.CREATE_PIPE com um nome de pipe especificado pelo usuário.
  • Pipe Público: Acessível por qualquer usuário com a permissão EXECUTE no pacote DBMS_PIPE.
  • Pipe Privado: Acessível por sessões com o mesmo usuário do 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.

Veja a seguir o fluxo de trabalho 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 Singleton

    • Um Singleton Pipe pode armazenar uma mensagem em cache no pipe, daí o nome "singleton".
    • A mensagem em um Pipe Singleton pode ser composta de 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 Singleton 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 Singleton Pipe Privado, 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
    • O Singleton Pipes armazena 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 Singleton Pipe é uma operação sem bloqueio.
  • Cache de Mensagem
    • Uma mensagem é armazenada em cache em um Pipe Singleton 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 usando DBMS_PIPE.SEND_MESSAGE.
    • Invalidação Automática: uma mensagem pode ser invalidada automaticamente depois que o tempo shelflife especificado tiver decorrido.
  • Nenhuma 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 Pipe Singleton Implícito permanece na memória do banco de dados até que haja uma mensagem em cache no pipe.

Operações de Pipe Singleton

Operação DBMS_PIPE Função ou Procedimento

Criar um Pipe Singleton Explícito

Função CREATE_PIPE

Armazenar uma mensagem no cache no Singleton Pipe

Procedimentos PACK_MESSAGE, Função SEND_MESSAGE

Ler uma mensagem em cache do Singleton Pipe

Função RECEIVE_MESSAGE, Procedimentos UNPACK_MESSAGE

Excluir uma mensagem no Singleton Pipe

Procedimento PURGE

Remover um Pipe Singleton Explícito

Função REMOVE_PIPE

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

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

Por padrão, depois que uma mensagem é invalidada com invalidação explícita ou implícita do Singleton Pipe, um DBMS_PIPE.RECEIVE_MESSAGE subsequente resulta em nenhuma mensagem sendo recebida. Para adicionar uma nova mensagem ao pipe, a mensagem deve ser armazenada no cache explicitamente chamando DBMS_PIPE.SEND_MESSAGE. Para evitar esse caso, quando nenhuma mensagem estiver disponível quando você ler um Pipe Singleton, poderá 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 Singleton Pipe está vazio.
  • Quando a mensagem em um Pipe Singleton é 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 Pipe Singleton 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 Pipe Singleton.

O uso de uma função de cache simplifica o trabalho com Pipes Singleton. Você não precisa tratar casos de falha para receber uma mensagem de um canal 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 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 Pipe Singleton.
  • Envie a mensagem para o pipe especificado na função de cache, especificando opcionalmente 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 RECEIVE_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 CREATE_PIPE Função 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

    Consulte Procedimentos PACK_MESSAGE e Função SEND_MESSAGE para obter mais informações.

  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 fornecer uma função de cache. Uma função de cache permite que você preencha automaticamente a mensagem em um pipe único.

  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 CREATE_PIPE Função 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 CREATE_PIPE Função para obter mais informações.