Eu realmente preciso de gatilhos para banco de dados relacional, por exemplo, PostgreSQL?


10

Eu sei que os gatilhos podem ser usados ​​para validar os dados armazenados para manter o banco de dados consistente. No entanto, por que não executar a validação de dados no lado do aplicativo antes de armazená-los no banco de dados?

Por exemplo, armazenamos clientes e queremos executar alguma validação que não pode ser feita facilmente no nível DDL. https://severalnines.com/blog/postgresql-triggers-and-stored-function-basics

Outro exemplo é a auditoria.

Atualizar

Como gatilhos e transações de banco de dados funcionam juntos. Por exemplo, se eu gostaria de executar a validação dos dados que estão sendo inseridos. Isso é feito dentro de uma transação. O que acontece antes: a transação é confirmada ou o gatilho é executado?


However, why not perform validation of data on the application side before storing them into the database?bem, esses dois não são mutuamente exclusivos. É provável que você valide coisas diferentes dos dois lados. Embora as validações no lado do aplicativo sejam centradas nos negócios, as validações no banco de dados são mais centradas nos dados. Pense em um banco de dados alimentado por vários e diferentes aplicativos.
21419 Laiv

Você precisará inserir dados de uma fonte externa que está apenas fazendo um despejo irracional de dados no seu sistema? Nesse caso, você pode ter casos em que precisa dos dados inseridos em um formato inválido para correção posterior. Nesse caso, os gatilhos causarão problemas infinitos. Apenas tenha isso em mente. Às vezes você não quer que um gatilho seja executado.
Greg Burghardt

Sua atualização deve ser uma pergunta por si só, talvez no SO, mas sua pergunta já tem uma resposta no Database Administrators.SE . Em resumo, mesmo um gatilho "após a atualização" é executado antes da transação ser confirmada e, se uma exceção for lançada dentro do gatilho, isso causará uma reversão.
Doc Brown

@GregBurghardt A maioria dos bancos de dados possui instruções que podem ser usadas para desativar gatilhos para esses tipos de atividades.
Blrfl

1
@Blrfl: Sim, mas você precisa estar ciente de que esses gatilhos podem ser desabilitados temporariamente para todos os usuários conectados, quando você quiser desabilitar condicionalmente essas verificações para a sessão atual.
Greg Burghardt

Respostas:


12

Depende do tipo de sistema de aplicativos que você está construindo:

  • se você estiver criando um sistema centralizado em aplicativos que contenha apenas um aplicativo principal, com um banco de dados dedicado especificamente para esse aplicativo e, idealmente, uma equipe responsável por desenvolver aplicativos e bancos de dados lado a lado, poderá manter toda a lógica de validação e também auditar lógica dentro do aplicativo.

    O principal benefício disso é que você não precisa distribuir a lógica de negócios entre aplicativo e banco de dados; portanto, manter e evoluir o sistema geralmente fica mais fácil. Como bônus, você não vincula muito o aplicativo a um tipo específico de fornecedor de DBMS ou DBMS. Essa abordagem é obviamente necessária se seu aplicativo quiser usar um sistema de banco de dados leve que não forneça gatilhos.

  • Se, no entanto, você criar um sistema no qual muitos aplicativos diferentes compartilham um banco de dados comum, e não é possível prever antecipadamente quais aplicativos serão gravados no futuro ou quais equipes desenvolverão aplicativos para preencher dados no banco de dados no futuro. é melhor que seu banco de dados seja responsável por garantir o máximo de consistência de dados possível. E é aí que os gatilhos são realmente úteis. Em sistemas maiores, as restrições referenciais geralmente não são suficientes para isso, mas um gatilho que chama um procedimento armazenado pode implementar quase qualquer tipo de validação necessária.

Outro motivo para o uso de gatilhos pode ser o desempenho: em modelos de dados complexos, não é incomum encontrar regras de consistência complexas que exigem o uso de muitos dados adicionais que não fazem parte do conjunto de trabalho atual disponível no aplicativo cliente. Transferir todos esses dados pela rede primeiro para possibilitar a validação no lado do cliente pode ter um impacto notável no desempenho.

Consulte também este post antigo do SE: Application Logic Vs DB Triggers para limpeza de banco de dados

Portanto, decida por si mesmo que tipo de sistema você está construindo e poderá tomar uma decisão fundamentada se os gatilhos forem a ferramenta certa para o seu caso ou não.


3

Eu acho que a pergunta é sobre responsabilidade pela qualidade dos dados.

A resposta depende de como você vê o sistema.

Se você vê o banco de dados como um serviço independente, distinto e autônomo separado do aplicativo, o banco de dados é responsável por garantir a consistência e a qualidade dos dados que ele contém. Essencialmente, porque esse banco de dados pode ser usado por um aplicativo diferente, não pode contar com o segundo aplicativo com os mesmos comportamentos de consistência e qualidade. Nessas circunstâncias, o banco de dados precisa ser projetado para expor uma API e um comportamento autônomo. Nesta visão, existem pelo menos dois aplicativos, um deles é o banco de dados e o outro é o aplicativo que o utiliza.

Por outro lado, o banco de dados pode ser considerado uma forma complicada de arquivo que está sob o controle direto e total do aplicativo. Nesse sentido, o banco de dados passa a ser uma pura ferramenta de serialização e navegação de documentos. Ele pode fornecer alguns comportamentos avançados para dar suporte a consultas e manutenção de documentos (como JSON ou ferramentas XML), mas, novamente, não é necessário (como a maioria dos fluxos de arquivos). Nesse caso, é de inteira responsabilidade do programa manter o formato e o conteúdo corretos no arquivo. Nesta visão, há um aplicativo.

Nos dois modos de exibição, a próxima pergunta é como dar suporte ao uso do banco de dados como um arquivo sofisticado ou como um serviço separado. Você pode conseguir isso:

  • usando as ferramentas que a plataforma de banco de dados fornece na forma de tabelas / visualizações / procedimentos armazenados / gatilhos / etc ...
  • agrupando o próprio banco de dados em um serviço que todos os clientes devem usar para acessar o banco de dados
  • agrupando o banco de dados em uma biblioteca que deve ser usada por todos os clientes para acessar os dados.

Cada um vem com seus próprios prós / contras e dependerá das restrições arquiteturais do ambiente em que o sistema opera.

Independentemente de qual visão você adote, sempre vale a pena validar os dados nos limites.

  • Validar os campos em uma interface do usuário que um usuário digita
  • Valide a solicitação de rede / API antes de deixar o cliente
  • Valide a solicitação de rede / API no servidor antes de fazer qualquer coisa
  • Validar os dados que estão sendo passados ​​para as regras de negócios
  • Valide os dados antes de persistir
  • Valide os dados após serem recuperados da persistência
  • Assim por diante e assim por diante

A quantidade de validação garantida em cada limite depende de quanto é arriscado não validá-lo.

  • multiplicando dois números juntos?
    • você recebe o número errado, isso é um problema?
  • invocando um procedimento em um determinado local de memória?
    • O que há nessa localização de memória?
    • O que acontece se o objeto não existir ou estiver em mau estado?
  • usando um regex em uma string contendo kanji?
    • O módulo regex pode lidar com unicode?
    • O regex pode lidar com unicode?

Centralizar a lógica de validação é bom, mas imho triggers não são uma boa maneira de implementar isso. Eu costumava trabalhar em um sistema em que vários aplicativos compartilhavam um banco de dados, com toda a lógica de validação e efeitos colaterais implementados no banco de dados por meio de gatilhos e procedimentos armazenados. Fiquei com a impressão de que é melhor ter um microsserviço na frente do banco de dados e implementar toda a lógica lá. A lógica não trivial dentro de um banco de dados SQL é um anti-padrão.
Joeri Sebrechts 14/02/19

1
@JoeriSebrechts Ok, vou morder: por que a lógica não trivial em um banco de dados é um antipadrão, e o que o torna mais antipadrão do que colocá-lo em um programa mantido separadamente?
Blrfl 14/02/19

@Blrfl Duas razões, a API para acessar a lógica no banco de dados é inferior a uma API de serviço da web (mais difícil de versão, mais difícil de usar, não é facilmente armazenada em cache, ...), e os bancos de dados dificultam a estrutura e a manutenção limpas do codebase hospedado dentro deles. Na minha experiência, é mais fácil hospedar a lógica em um serviço web na frente do banco de dados do que dentro desse banco de dados.
Joeri Sebrechts 15/02/19

@JoeriSebrechts Concordo que a maioria das plataformas de banco de dados fornece ferramentas ruins para implementar uma API credível, útil e de desenvolvimento. De muitas maneiras, é certamente um convite para sentir muita dor. Meu argumento foi que se trata de perspectiva, percebendo que o banco de dados é um arquivo sofisticado, ou que é realmente um serviço separado, leva à próxima pergunta: como envolvê-lo para suportar esse estilo de uso. Vou elaborar minha resposta para esclarecer isso.
Kain0_0 17/02/19

2

Não, você nunca deve usar gatilhos para validar.

O banco de dados é responsável apenas por sua própria integridade. Qualquer usuário enfrentando validação deve ser realizado pelo seu aplicativo.

Os bancos de dados executam três níveis de validação para integridade. O primeiro é a validação em nível de campo. Um campo pode ser obrigatório, se não houver valor (nulo), será um erro. Também pode ser uma restrição de verificação; um domínio tem um número enumerado de valores.

Em segundo lugar, existem relações entre tabelas. Em uma tabela, você armazena uma ou mais chaves estrangeiras, relacionando esta tabela com outras tabelas e exigindo que os valores sejam chaves válidas para a "outra tabela". Pense em um banco de dados de endereços, onde suportamos endereços de diferentes países. Uma chave de país em um endereço deve apontar para um país conhecido. Se os dados (por exemplo, um código postal) são válidos, não é uma preocupação dessa verificação de integridade.

Terceiro e mais complicado são os gatilhos. Como regra geral, eles devem abordar (trocadilhos não intencionados) as regras de integridade que são condicionais. Para voltar ao exemplo de endereço: se um país não tiver códigos postais, seria um problema se um país nesta lista tivesse um código postal. Portanto, a verificação seria: se este país não tiver códigos postais, o campo do código postal deverá ser nulo.

A validação é a preocupação do aplicativo. O fato de um código postal alemão consistir em apenas dígitos é uma verificação que o aplicativo deve fazer, não o banco de dados. Como a linha é fina, você pode precisar pensar / discutir em alguns casos, se algo deve estar em um gatilho (proteger a integridade do seu banco de dados) ou no aplicativo (validação voltada para o usuário).


Só queria acrescentar que, se o OP precisar adicionar uma regra de validação complexa que precisa estar no banco de dados, ele sempre poderá usar os procedimentos armazenados como uma alternativa mais segura.
Borjab 14/02/19

@ Borjab: Validação como em manter o banco de dados correto, talvez. Mas usuário enfrentando validação? Não.
Menno Hölscher

1
Sua primeira declaração diz "nunca use gatilhos para validação" , mas abaixo você escreve: "sim, você pode usar gatilhos para certos tipos de validação, e não é inerentemente claro onde traçar a linha". Isso parece bastante contraditório. Eu recomendaria excluir sua primeira frase, isso melhoraria bastante sua resposta. Ah, e sua última frase não responde à pergunta de atualização dos OPs, pois "antes / depois" não tem nada a ver com a transação. Eu recomendaria excluí-lo também. (veja meu comentário abaixo da pergunta dos OPs).
Doc Brown

@DocBrown A distinção é entre proteger o banco de dados contra corrupção e validação voltada para o usuário. Portanto, em "qualquer validação adicional", refiro-me à validação voltada para o usuário. Como eu poderia deixar essa distinção mais clara? Para começar, retirei o "mais".
Menno Hölscher

2
É perfeitamente bom fazer a validação no banco de dados. Assim como é bom fazê-lo no aplicativo. Ambos têm suas vantagens. Fazer a validação no aplicativo significa que você deve ser super cuidadoso sempre que executar o SQL sem o ORM, necessário para praticamente todos os aplicativos complexos.
Qwertie 18/02/19

1

A auditoria é um exemplo clássico do uso de gatilhos efetivamente. Encontrei alguns erros cometidos pelo testador (movendo um cliente de um nível de serviço para outro) graças a uma tabela de auditoria que foi implementada por gatilhos. Eu recomendo o uso de gatilhos para auditoria.

A validação pode ser feita no nível de front-end, mas vi erros estranhos no banco de dados que eu lidei (pessoas que nasceram em 3000 etc.) e, como alguns deles, eu me recomendo, recomendo ter uma camada extra de validação no banco de dados, apenas por precaução. Obviamente, esses tipos de erros podem ser evitados com restrições de verificação e muitas vezes são mais eficazes (no MS SQL, eles são o método preferido; sempre verifique a documentação).


1

Como a questão é se realmente precisamos de gatilhos para bancos de dados relacionais, aqui estão alguns outros casos de uso em que usar gatilhos:

  1. Para auditoria, conforme descrito nas outras respostas.
  2. Auditoria no sentido mais amplo: se uma entrada do banco de dados for alterada, um gatilho poderá registrar o evento para pós-processamento assícrono, por exemplo, exportações noturnas para outro aplicativo.
  3. Gatilhos para visualizações: gatilhos podem ser definidos instead of. Com isso, é possível inserir, atualizar e excluir entradas de uma exibição. Os gatilhos podem espalhar essas ações em várias tabelas. Essa é uma maneira de disponibilizar uma exibição restrita sem expor os detalhes das tabelas subjacentes.
  4. Para salvar explicitamente os retornos do banco de dados: assuma uma relação N: M entre a tabela A e B e uma tabela intermediária R. Você pode definir restrições de chave estrangeira de R a A e também B especificando que a entrada em R deve ser descartada se a entrada correspondente em B é excluída. Entretanto, a lógica de negócios às vezes exige que as entradas em A tenham pelo menos uma relação com uma entrada em B. Nesse caso, um gatilho na exclusão de R pode ajudar a impor essa lógica: se, para uma entrada em A, a última entrada em R é excluído, o gatilho pode excluir A. Na visualização centralizada no aplicativo, são necessárias pelo menos duas voltas. Este é um exemplo de validação. Outros exemplos são concebíveis: ao lado dos casos de uso (1), (2),
  5. Confiança: às vezes, os administradores de banco de dados alteram as entradas na linha de comando que não usam seu aplicativo. Os administradores trabalham com cuidado e sabem o que fazem. No entanto, às vezes eles podem estar errados. Se a consistência é crítica, um gatilho é o cinto de segurança.

Como uma desvantagem, a lógica comercial é distribuída entre as camadas e essa é uma grande desvantagem para manutenção. Como outro autor escreveu, é um limite fino entre aplicativo e banco de dados e a escolha nem sempre é clara. Minha opinião pessoal é que os gatilhos colocam um fardo para os desenvolvedores. Eles podem economizar tempo em desenvolvimento. Definitivamente, eles aprimoram a experiência do usuário porque aumentam o desempenho em conexões de rede lentas.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.