Sempre que preciso criar um novo banco de dados, passo bastante tempo pensando em como devo configurar o esquema do banco de dados para manter um log de auditoria das alterações.
Algumas perguntas já foram feitas aqui sobre isso, mas não concordo que exista uma melhor abordagem única para todos os cenários:
- Design de banco de dados para revisões
- Melhor design para uma tabela de banco de dados de auditoria de log de alterações
- Ideias sobre design de banco de dados para captura de trilhas de auditoria
Também deparei com este artigo interessante sobre como manter um log de alterações no banco de dados que tenta listar os prós e contras de cada abordagem. É muito bem escrito e tem informações interessantes, mas tornou minhas decisões ainda mais difíceis.
Minha pergunta é: Existe uma referência que eu possa usar, talvez um livro ou algo como uma árvore de decisão que eu possa me referir para decidir qual caminho devo seguir com base em algumas variáveis de entrada, como:
- A maturidade do esquema do banco de dados
- Como os logs serão consultados
- A probabilidade de que será necessário recriar registros
- O que é mais importante: desempenho de gravação ou leitura
- Natureza dos valores que estão sendo registrados (sequência, números, blobs)
- Espaço de armazenamento disponível
As abordagens que eu sei são:
1. Adicione colunas para data e usuário criados e modificados
Exemplo de tabela:
- Eu iria
- value_1
- value_2
- value_3
- Data de criação
- data modificada
- criado por
- modificado por
Contras principais: perdemos o histórico das modificações. Não é possível reverter após a confirmação.
2. Insira apenas tabelas
- Eu iria
- value_1
- value_2
- value_3
- de
- para
- excluído (booleano)
- do utilizador
Contras principais: Como manter as chaves estrangeiras atualizadas? Espaço enorme necessário
3. Crie uma tabela de histórico separada para cada tabela
Exemplo da tabela de histórico:
- Eu iria
- value_1
- value_2
- value_3
- value_4
- do utilizador
- excluído (booleano)
- timestamp
Contras principais: precisa duplicar todas as tabelas auditadas. Se o esquema mudar, será necessário migrar todos os logs também.
4. Crie uma tabela de histórico consolidada para todas as tabelas
Exemplo da tabela de histórico:
- Nome da tabela
- campo
- do utilizador
- novo valor
- excluído (booleano)
- timestamp
Contras principais: poderei recriar os registros (reversão) se necessário com facilidade? A coluna new_value precisa ser uma string enorme para suportar todos os diferentes tipos de coluna.
fonte
Respostas:
Um método usado por algumas plataformas wiki é separar os dados de identificação e o conteúdo que você está auditando. Isso aumenta a complexidade, mas você acaba com uma trilha de auditoria de registros completos, não apenas as listagens de campos que foram editados que precisam ser combinados para fornecer ao usuário uma idéia da aparência do registro antigo.
Por exemplo, se você tivesse uma tabela chamada Oportunidades para rastrear ofertas de vendas, criaria duas tabelas separadas:
Oportunidades
Opportunities_Content (ou algo parecido)
A tabela Oportunidades teria informações que você usaria para identificar exclusivamente o registro e abrigaria a chave primária que você referenciaria para seus relacionamentos de chave estrangeira. A tabela Opportunities_Content conteria todos os campos que seus usuários podem alterar e para os quais você deseja manter uma trilha de auditoria. Cada registro na tabela Conteúdo incluiria sua própria PK e os dados de data de modificação e data de modificação. A tabela Oportunidades incluiria uma referência à versão atual, além de informações sobre quando o registro principal foi criado originalmente e por quem.
Aqui está um exemplo simples:
E o conteúdo:
Eu provavelmente tornaria a PK da tabela de conteúdo uma chave de várias colunas do PageID e da Revisão, desde que a Revisão fosse um tipo de identidade. Você usaria a coluna Revisão como o FK. Em seguida, você puxa o registro consolidado JOINing assim:
Pode haver alguns erros lá em cima ... isso está no topo da minha cabeça. No entanto, você deve ter uma idéia de um padrão alternativo.
fonte
PageContent.PageID
FK paraPage.ID
ePage.CurrentRevision
FK paraPageContent.Revision
? Essa dependência é realmente circular?id, revision_id
; mais uma mesa de junção, realmente. Isso parece um pouco fedorento para mim. Que vantagem isso tem sobre a abordagem 3 no OP (tabela de histórico por tabela auditada)?Se você estiver usando o SQL Server 2008, provavelmente deverá considerar o Change Data Capture. Isso é novo para 2008 e pode economizar uma quantidade considerável de trabalho.
fonte
Não conheço nenhuma referência, mas tenho certeza de que alguém escreveu alguma coisa.
No entanto, se o objetivo é simplesmente ter um registro do que aconteceu - o uso mais comum de um log de auditoria -, por que não simplesmente manter tudo:
Presumivelmente, isso é mantido por um gatilho.
fonte
Criaremos um pequeno banco de dados de exemplo para um aplicativo de blog. São necessárias duas tabelas:
blog
: armazena um ID de postagem exclusivo, o título, o conteúdo e um sinalizador excluído.audit
: armazena um conjunto básico de alterações históricas com um ID de registro, o ID da postagem do blog, o tipo de alteração (NEW, EDIT ou DELETE) e a data / hora dessa alteração. O SQL a seguir criablog
e indexa a coluna excluída:O SQL a seguir cria a
audit
tabela. Todas as colunas são indexadas e uma chave estrangeira é definida para audit.blog_id que faz referência a blog.id. Portanto, quando EXCLUEM fisicamente uma entrada de blog, seu histórico completo de auditoria também é removido.fonte
Eu acho que não há nada como uma árvore de decisão. Uma vez que alguns dos prós e contras (ou requisitos) não são realmente contáveis. Como você mede a maturidade, por exemplo?
Portanto, basta alinhar os requisitos de negócios para o log de auditoria. Tente prever como esses requisitos podem mudar no futuro e gerar seus requisitos técnicos. Agora você pode compará-lo com os prós e contras e escolher a opção certa / melhor.
E tenha certeza, não importa como você decida, sempre haverá alguém que acha que você tomou a decisão errada. No entanto, você fez sua lição de casa e justifica sua decisão.
fonte