Melhor design para uma tabela de banco de dados de log de mudanças / auditoria? [fechadas]

114

Eu preciso criar uma tabela de banco de dados para armazenar log de alterações / auditoria diferentes (quando algo foi adicionado, excluído, modificado, etc). Não preciso armazenar informações particularmente detalhadas, então estava pensando em algo como:

  • id (para evento)
  • usuário que o acionou
  • nome do evento
  • Descrição do Evento
  • carimbo de data / hora do evento

Estou faltando alguma coisa aqui? Obviamente, posso continuar melhorando o design, embora não planeje complicá-lo (criar outras tabelas para tipos de eventos ou coisas assim está fora de questão, pois é uma complicação para a minha necessidade).

rcphq
fonte
Eu li sua resposta e estou surpreso que ninguém fale sobre Direito. Eu sei que algumas leis ou documentos de boas práticas explicam como DEVEMOS implementar uma tabela de auditoria (somente leitura). Mas não tenho mais informações do que isso. Só sei que existe. Estou pensando na trilha de auditoria no CFR 21 parte 11.
Bastien Vandamme

Respostas:

69

No projeto em que estou trabalhando, o registro de auditoria também começou a partir de um design minimalista, como o que você descreveu:

event ID
event date/time
event type
user ID
description

A ideia era a mesma: manter as coisas simples.

No entanto, rapidamente se tornou óbvio que esse design minimalista não era suficiente. A auditoria típica se resumia a perguntas como esta:

Who the heck created/updated/deleted a record 
with ID=X in the table Foo and when?

Então, para poder responder a essas perguntas rapidamente (usando SQL), acabamos tendo duas colunas adicionais na tabela de auditoria

object type (or table name)
object ID

Foi quando o design de nosso registro de auditoria realmente se estabilizou (por alguns anos agora).

É claro que a última "melhoria" funcionaria apenas para tabelas que tivessem chaves substitutas. Mas adivinha? Todas as nossas tabelas que valem a pena auditar possuem essa chave!

Yarik
fonte
O único problema que tive com este design (uma trilha de auditoria baseada em 'descrição') é com a localização do idioma usado nesse campo.
Sam Wilson
@Sam não vejo esse problema, se a mensagem é gerada pelo sistema, basta usar uma chave aqui para a string de tradução;
JCM
4
@Hiru: Quando você "mistura" dois ou mais conceitos distintos em uma coluna, na maioria das vezes o tiro sai pela culatra, mais cedo ou mais tarde. Por exemplo, se você "misturar" o tipo de evento e o tipo de objeto, isso causará impacto em consultas como "mostre-me os registros de todos os objetos de um determinado tipo" e "mostre-me os registros de todos os eventos de um determinado tipo" (as consultas seriam mais complicado e provavelmente funcionaria muito mais devagar).
Yarik
3
Além dessas colunas, pode-se ter uma coluna extra para descrição estruturada / carga útil do evento estruturado . Essa coluna manteria os detalhes do evento (de qualquer complexidade) em um formato legível por computador, XML / JSON. Fácil de serializar, de consultar (pelo menos em Postgres / MSSQL), de raciocinar.
turdus-merula
1
@Benjamin: A resposta está no modelo de domínio (também conhecido como modelo de negócios). Se o modelo permite a criação simultânea de entidades (por exemplo, como parte de uma transação lógica), não vejo nenhum problema em ter vários registros de log com exatamente o mesmo carimbo de data / hora. Por exemplo, se a criação de um pedido de compra (como uma transação) pode incluir a criação de N itens de pedido, todos os registros de log 1 + N correspondentes teriam o mesmo carimbo de data / hora. A análise subsequente de tal registro poderia tirar vantagem disso, tratando esses registros 1 + N não como independentes, mas como elementos de uma transação lógica. Espero que isso faça sentido.
Yarik
24

Também registramos valores antigos e novos e a coluna de onde eles vêm, bem como a chave primária da tabela que está sendo auditada em uma tabela de detalhes de auditoria. Pense no que você precisa da tabela de auditoria? Você não quer apenas saber quem fez uma alteração e quando, mas quando uma alteração ruim acontece, você quer uma maneira rápida de colocar os dados de volta.

Enquanto estiver projetando, você deve escrever o código para recuperar os dados. Quando precisa se recuperar, geralmente é com pressa, é melhor já estar preparado.

HLGEM
fonte
1
Isso é muito bom. Não entendo por que as pessoas ignoram as últimas postagens.
Maddy.Shik
3
A fonte de eventos é uma abordagem alternativa para fornecer funcionalidade de reversão enquanto mantém o histórico.
Sam
23

Existem várias outras coisas que você pode querer auditar, como nomes de tabelas / colunas, computador / aplicativo a partir do qual foi feita uma atualização e muito mais.

Agora, isso depende de quão detalhada você realmente precisa de auditoria e em que nível.

Começamos a construir nossa própria solução de auditoria baseada em gatilhos e queríamos auditar tudo e também ter uma opção de recuperação em mãos. Isso acabou sendo muito complexo, então acabamos fazendo a engenharia reversa da ferramenta ApexSQL Audit baseada em gatilhos para criar nossa própria solução personalizada.

Dicas:

  • Incluir valores antes / depois

  • Incluir 3-4 colunas para armazenar a chave primária (no caso de ser uma chave composta)

  • Armazene dados fora do banco de dados principal, conforme já sugerido por Robert

  • Gaste uma quantidade razoável de tempo preparando relatórios - especialmente aqueles que você pode precisar para recuperação

  • Planeje armazenar o nome do host / aplicativo - isso pode ser muito útil para rastrear atividades suspeitas

Kenneth Hampton
fonte
2
Por que você faria a engenharia reversa em vez de comprar?
Jowen
1
mais controle sobre o produto
Tebe
1
Espero que eles não tenham processado você.
Classificador
9

Existem muitas respostas interessantes aqui e em questões semelhantes. As únicas coisas que posso acrescentar por experiência pessoal são:

  1. Coloque sua tabela de auditoria em outro banco de dados. Idealmente, você deseja separação dos dados originais. Se você precisa restaurar seu banco de dados, você realmente não deseja restaurar a trilha de auditoria.

  2. Desnormalize tanto quanto razoavelmente possível. Você deseja que a tabela tenha o mínimo possível de dependências dos dados originais. A tabela de auditoria deve ser simples e rápida para recuperar dados. Sem junções ou pesquisas extravagantes em outras tabelas para obter os dados.

Robert4Real
fonte
8
Os dados não normalizados seriam realmente mais rápidos de ler em comparação com os dados normalizados com índices apropriados? (Toda a duplicação não resultaria na leitura de mais dados do HDD?)
Sam
4

O que temos em nossa mesa: -

Primary Key
Event type (e.g. "UPDATED", "APPROVED")
Description ("Frisbar was added to blong")
User Id
User Id of second authoriser
Amount
Date/time
Generic Id
Table Name

O id genérico aponta para uma linha na tabela que foi atualizada e o nome da tabela é o nome dessa tabela como uma string. Não é um bom design de banco de dados, mas muito utilizável. Todas as nossas tabelas têm uma única coluna de chave substituta, então isso funciona bem.

WW.
fonte
2
O que "quantia" representa?
turdus-merula
É uma aplicação financeira, portanto, é o valor em dólares da coisa que está sendo autorizada, etc.
WW.
4

Em geral, a auditoria personalizada (criação de várias tabelas) é uma opção ruim. Os gatilhos de banco de dados / tabela podem ser desativados para pular algumas atividades de log. As tabelas de auditoria personalizadas podem ser adulteradas. Exceções podem ocorrer para desativar o aplicativo. Sem mencionar as dificuldades em projetar uma solução robusta. Até agora, vejo casos muito simples nesta discussão. Você precisa de uma separação completa do banco de dados atual e de quaisquer usuários privilegiados (DBA, Desenvolvedores). Todos os RDBMSs convencionais fornecem recursos de auditoria que nem mesmo o DBA consegue desabilitar, violar em segredo. Portanto, o recurso de auditoria fornecido pelo fornecedor de RDBMS deve ser a primeira opção. Outra opção seria um leitor de log de transações de terceiros ou um leitor de log personalizado que empurra informações decompostas em um sistema de mensagens que termina em algumas formas de Data Warehouse de auditoria ou manipulador de eventos em tempo real. Em suma: O Arquiteto de Soluções / "Arquiteto Prático de Dados" precisa se envolver no destino de tal sistema com base nos requisitos. Normalmente, é uma coisa muito séria entregar aos desenvolvedores para a solução.

Joel Mamedov
fonte
3

Há muitas maneiras de fazer isso. Minha maneira favorita é:

  1. Adicione um mod_usercampo à sua tabela de origem (aquele que você deseja registrar).

  2. Crie uma tabela de registro que contenha os campos que deseja registrar, além de um campo log_datetimee seq_num. seq_numé a chave primária.

  3. Crie um gatilho na tabela de origem que insere o registro atual na tabela de log sempre que qualquer campo monitorado for alterado.

Agora você tem um registro de todas as alterações e de quem as fez.

JosephStyons
fonte
Então ... o que o campo mod_user deve fazer?
conny
1
Diga quem fez a mudança. O código de atualização deve incluir algo para definir esse campo para o usuário atual.
JosephStyons
E quanto às exclusões, então? Se você deletar uma linha, como você lida com o valor da coluna mod_user?
Kenn Cal
@KennCal Triggers podem usar tabelas virtuais, você pode ver os dados antes e depois dentro do mesmo gatilho. Não importa a operação. stackoverflow.com/questions/6282618/…
Renan Cavalieri
2
@KennCal Você está correto, o gatilho de exclusão precisará armazenar essas informações para você. O diabo está nos detalhes - se você estiver usando autenticação SQL, o gatilho pode simplesmente executar [selecionar CURRENT_USER]. Se for um aplicativo cliente, o código do cliente precisará anunciar quem é. Se for uma chamada de API, o usuário excluído precisa ser um parâmetro obrigatório para a chamada.
JosephStyons
1

De acordo com o princípio da separação:

  1. As tabelas de dados de auditoria precisam ser separadas do banco de dados principal. Como os bancos de dados de auditoria podem ter muitos dados históricos, faz sentido do ponto de vista da utilização da memória mantê-los separados.

  2. Não use gatilhos para auditar todo o banco de dados, porque você acabará com uma confusão de bancos de dados diferentes para suportar. Você terá que escrever um para DB2, SQLServer, Mysql, etc.

Bhagat007
fonte