⌘K

12 – SQL no PostgreSQL: Automatizando Processos com Triggers (Gatilhos)

Last updated

No nosso último post, exploramos o universo da segurança de dados e vimos como controlar permissões de acesso usando Roles, GRANT e REVOKE. Hoje, vamos falar sobre como dar “superpoderes” de automação ao seu banco de dados.

Imagine que você precisa manter uma tabela de auditoria que registra cada alteração feita nos servidores da sua infraestrutura. Ou que, sempre que o status de um microsserviço mudar para “inativo”, você queira calcular automaticamente o tempo total de downtime e registrar em outra tabela.

Você poderia fazer isso direto no código da sua aplicação (no backend), mas se múltiplas APIs ou scripts Python acessarem o mesmo banco, você terá que replicar essa lógica em todos os lugares. A solução ideal e centralizada para esse problema no PostgreSQL são as Triggers (Gatilhos).

O que é uma Trigger?

Uma Trigger é um objeto do banco de dados que escuta eventos específicos de manipulação de dados (DML) — como um INSERT, UPDATE ou DELETE — e reage a eles executando uma função de forma 100% automática.

No PostgreSQL, a arquitetura de uma Trigger funciona em duas partes:

  1. A Função da Trigger (Trigger Function): O bloco de código que define o que deve ser feito.
  2. O Gatilho (Trigger): A regra que define quando e em qual tabela aquela função deve ser disparada.

Duas Variáveis Secretas: NEW e OLD

Quando uma Trigger entra em ação, o PostgreSQL disponibiliza automaticamente duas variáveis especiais que nos permitem inspecionar os dados que estão mudando:

  • NEW: Guarda o registro que acabou de ser inserido ou os novos dados que estão sendo atualizados.
  • OLD: Guarda o registro antigo, exatamente como ele era antes de sofrer um UPDATE ou DELETE.

Cenário Prático: Criando um Sistema de Auditoria Automático

Vamos criar um cenário real de infraestrutura. Temos a nossa tabela principal servidores e queremos que o Postgres alimente uma tabela secundária chamada historico_servidores toda vez que as especificações de um servidor mudarem (como vCPUs ou Memória).

Passo 1: Criando a tabela de histórico

CREATE TABLE historico_servidores (
    id SERIAL PRIMARY KEY,
    id_servidor INT,
    nome_servidor VARCHAR(100),
    vcpus_antigo INT,
    vcpus_novo INT,
    alterado_em TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

Passo 2: Criando a Função da Trigger (Trigger Function)

No Postgres, usamos a linguagem procedural PL/pgSQL para escrever a lógica da função. Ela deve retornar o tipo TRIGGER.

CREATE OR REPLACE FUNCTION fn_auditar_alteracao_servidor()
RETURNS TRIGGER AS $$
BEGIN
    -- Verifica se houve mudança real nos recursos antes de salvar
    IF (OLD.vcpus IS DISTINCT FROM NEW.vcpus) OR (OLD.memoria_gb IS DISTINCT FROM NEW.memoria_gb) THEN
        INSERT INTO historico_servidores (id_servidor, nome_servidor, vcpus_antigo, vcpus_novo)
        VALUES (OLD.id, OLD.nome, OLD.vcpus, NEW.vcpus);
    END IF;

    -- Em triggers do tipo BEFORE ou AFTER, sempre retorne NEW para prosseguir com a operação
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

Passo 3: Criando a Trigger propriamente dita

Agora, associamos a função à tabela servidores. Queremos que esse gatilho dispare depois (AFTER) de cada atualização (UPDATE) que acontecer em cada linha (FOR EACH ROW).

CREATE TRIGGER trg_servidor_alterado
AFTER UPDATE ON servidores
FOR EACH ROW
EXECUTE FUNCTION fn_auditar_alteracao_servidor();

Pronto! A partir de agora, qualquer UPDATE feito na tabela servidores — seja via aplicação Web, script de automação ou CLI — gerará automaticamente uma linha de auditoria na tabela de histórico, sem que a aplicação precise se preocupar com isso.

Boas Práticas e Cuidados Importantes (O olhar de Infraestrutura)

Embora as Triggers sejam ferramentas fantásticas para garantir a integridade dos dados, no mundo DevOps e de alta performance elas devem ser usadas com muita moderação.

  1. O Impacto Oculto na Performance: Uma Trigger roda na mesma transação que o comando principal. Se você fizer um INSERT em lote de 10.000 linhas e tiver uma trigger do tipo FOR EACH ROW, o Postgres executará a função 10.000 vezes. Isso pode deixar suas operações de escrita extremamente lentas.
  2. Dificuldade de Debug: Como as triggers rodam invisíveis por baixo dos panos, quando um bug acontece, o desenvolvedor pode achar que o erro está no código da aplicação, quando na verdade está em uma validação interna do banco de dados. Mantenha as triggers bem documentadas.
  3. Evite Loops Infinitos: Cuidado para não criar uma Trigger na Tabela A que faz um update na Tabela B, enquanto a Tabela B tem outra trigger que faz um update de volta na Tabela A. Isso causará um estouro de pilha no banco.

Conclusão

As Triggers são o recurso definitivo para garantir que certas regras de negócio e logs de auditoria sejam blindados diretamente no banco de dados, independentemente de quantas aplicações ou ferramentas de terceiros alterem seus registros. Elas automatizam o trabalho pesado e garantem a consistência.

Com as Triggers dominadas, passamos por toda a fundação operacional e de automação no PostgreSQL. É hora de fecharmos a nossa série de SQL consolidando as boas práticas em um formato padrão de mercado.

No próximo post da nossa seção de SQL, vamos entender as diferenças fundamentais entre duas siglas muito famosas na Engenharia de Software e de Infraestrutura: DML, DDL, DCL e DTL. Vamos fazer um resumão visual de como mapear cada comando que aprendemos até aqui dentro dessas categorias do SQL. Até lá!

Você já usou Triggers para criar sistemas de logs ou prefere deixar essa lógica de auditoria centralizada no código do seu backend? Deixe sua opinião aqui nos comentários!

Still stuck? How can we help? Get Help