La meilleure conception pour une table de base de données de journal des modifications / d'audit? [fermé]

114

J'ai besoin de créer une table de base de données pour stocker différents journaux de modification / audit (quand quelque chose a été ajouté, supprimé, modifié, etc.). Je n'ai pas besoin de stocker des informations particulièrement détaillées, alors je pensais à quelque chose du genre:

  • id (pour l'événement)
  • utilisateur qui l'a déclenché
  • Nom de l'événement
  • description de l'évenement
  • horodatage de l'événement

Est-ce que j'ai râté quelque chose? Évidemment, je peux continuer à améliorer la conception, même si je ne prévois pas de la compliquer (créer d'autres tables pour des types d'événements ou des trucs comme ça est hors de question car c'est une complication pour mon besoin).

rcphq
la source
J'ai lu votre réponse et je suis surpris que personne ne parle de Law. Je sais que certaines lois ou documents de bonnes pratiques expliquent comment nous DEVONS implémenter une table d'audit (en lecture seule). Mais je n'ai pas plus d'informations que cela. Je sais juste que ça existe. Je pense à Audit trail dans CFR 21 part 11.
Bastien Vandamme

Réponses:

70

Dans le projet sur lequel je travaille, le journal d'audit est également parti d'un design très minimaliste, comme celui que vous avez décrit:

event ID
event date/time
event type
user ID
description

L'idée était la même: garder les choses simples.

Cependant, il est rapidement devenu évident que ce design minimaliste n'était pas suffisant. L'audit typique se résumait à des questions comme celle-ci:

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

Ainsi, afin de pouvoir répondre rapidement à ces questions (en utilisant SQL), nous avons fini par avoir deux colonnes supplémentaires dans le tableau d'audit

object type (or table name)
object ID

C'est à ce moment que la conception de notre journal d'audit s'est vraiment stabilisée (depuis quelques années maintenant).

Bien sûr, la dernière "amélioration" ne fonctionnerait que pour les tables qui avaient des clés de substitution. Mais devinez quoi? Toutes nos tables qui méritent d'être vérifiées ont une telle clé!

Yarik
la source
Le seul problème que j'ai eu avec cette conception (une piste d'audit basée sur une «description») est de localiser la langue utilisée dans ce domaine.
Sam Wilson
@Sam Je ne vois pas un tel problème, si le message est généré par le système, utilisez simplement une clé ici pour la chaîne de traduction;
JCM
4
@Hiru: Lorsque vous "mélangez" deux ou plusieurs concepts distincts dans une même colonne, le plus souvent, cela va se retourner, tôt ou tard. Par exemple, si vous "mêlez" le type d'événement et le type d'objet, cela aurait un impact sur les requêtes telles que "montre-moi les enregistrements pour tous les objets du type donné" et "montre-moi les enregistrements pour tous les événements d'un type donné" (les requêtes seraient plus compliqué et fonctionnerait probablement beaucoup plus lentement).
Yarik
3
En plus de ces colonnes, on peut avoir une colonne supplémentaire pour la description structurée / la charge utile d'événements structurés . Cette colonne contiendrait les détails de l'événement (quelle que soit la complexité) dans un format lisible par ordinateur, XML / JSON. Facile à sérialiser, à interroger (au moins dans Postgres / MSSQL), à raisonner.
turdus-merula
1
@Benjamin: La réponse est dans le modèle de domaine (aka business model). Si le modèle permet la création simultanée d'entités (par exemple dans le cadre d'une transaction logique), je ne vois aucun problème à avoir plusieurs enregistrements de journal avec exactement le même horodatage. Par exemple, si la création d'un bon de commande (en tant que transaction) peut inclure la création de N articles de commande, alors tous les enregistrements de journal 1 + N correspondants auront le même horodatage. Une analyse ultérieure d'un tel journal pourrait en tirer parti, en traitant ces enregistrements 1 + N non pas comme des enregistrements indépendants mais comme des éléments d'une transaction logique. J'espère que cela a du sens.
Yarik
24

Nous enregistrons également les anciennes et les nouvelles valeurs et la colonne dont elles proviennent ainsi que la clé primaire de la table en cours d'audit dans un tableau détaillé d'audit. Vous pensez à quoi vous avez besoin de la table d'audit? Non seulement vous voulez savoir qui a effectué un changement et quand, mais quand un mauvais changement se produit, vous voulez un moyen rapide de remettre les données.

Pendant que vous concevez, vous devez écrire le code pour récupérer les données. Lorsque vous avez besoin de récupérer, il est généralement pressé, mieux vaut être déjà préparé.

HLGEM
la source
1
C'est vraiment bien, je ne comprends pas pourquoi les gens ignorent les derniers messages.
Maddy.Shik
3
L'approvisionnement en événements est une approche alternative pour fournir une fonctionnalité de restauration tout en conservant l'historique.
Sam
23

Vous voudrez peut-être auditer plusieurs autres éléments, tels que les noms de table / colonne, l'ordinateur / l'application à partir duquel une mise à jour a été effectuée, etc.

Maintenant, cela dépend du niveau d'audit détaillé dont vous avez vraiment besoin et à quel niveau.

Nous avons commencé à créer notre propre solution d'audit basée sur les déclencheurs, et nous voulions tout auditer et avoir également une option de récupération à portée de main. Cela s'est avéré trop complexe, nous avons donc procédé au reverse engineering de l'outil tiers ApexSQL Audit basé sur des déclencheurs pour créer notre propre solution personnalisée.

Conseils:

  • Inclure les valeurs avant / après

  • Inclut 3-4 colonnes pour stocker la clé primaire (au cas où il s'agirait d'une clé composite)

  • Stocker les données en dehors de la base de données principale comme déjà suggéré par Robert

  • Passez un temps décent à préparer les rapports, en particulier ceux dont vous pourriez avoir besoin pour la récupération

  • Planifiez le stockage du nom de l'hôte / de l'application - cela peut s'avérer très utile pour suivre les activités suspectes

Kenneth Hampton
la source
2
Pourquoi le désosseriez-vous au lieu de l'acheter?
Jowen
1
plus de contrôle sur le produit
Tebe
1
J'espère qu'ils ne vous ont pas poursuivi.
Trieur
9

Il y a beaucoup de réponses intéressantes ici et dans des questions similaires. Les seules choses que je peux ajouter par expérience personnelle sont:

  1. Mettez votre table d'audit dans une autre base de données. Idéalement, vous souhaitez une séparation des données d'origine. Si vous avez besoin de restaurer votre base de données, vous ne souhaitez pas vraiment restaurer la piste d'audit.

  2. Dénormalisez autant que raisonnablement possible. Vous voulez que la table ait le moins de dépendances possible avec les données d'origine. La table d'audit doit être simple et rapide comme l'éclair pour récupérer les données. Pas de jointures ou de recherches fantaisistes dans d'autres tables pour accéder aux données.

Robert4Real
la source
8
Les données non normalisées seraient-elles vraiment plus rapides à lire que les données normalisées avec des index appropriés? (Est-ce que toute la duplication n'entraînerait pas la lecture de plus de données sur le disque dur?)
Sam
4

Ce que nous avons dans notre tableau: -

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

L'ID générique pointe vers une ligne de la table qui a été mise à jour et le nom de la table est le nom de cette table sous forme de chaîne. Pas une bonne conception de base de données, mais très utilisable. Toutes nos tables ont une seule colonne de clé de substitution, donc cela fonctionne bien.

WW.
la source
2
Que signifie «montant»?
turdus-merula
C'est une application financière, donc c'est la valeur en dollars de la chose autorisée, etc.
WW.
4

En général, l'audit personnalisé (création de diverses tables) est une mauvaise option. Les déclencheurs de base de données / table peuvent être désactivés pour ignorer certaines activités du journal. Les tables d'audit personnalisées peuvent être altérées. Des exceptions peuvent avoir lieu et entraîner une baisse de l'application. Sans parler des difficultés à concevoir une solution robuste. Jusqu'à présent, je vois un cas très simple dans cette discussion. Vous avez besoin d'une séparation complète de la base de données actuelle et de tous les utilisateurs privilégiés (DBA, développeurs). Tous les SGBDR traditionnels fournissent des fonctionnalités d'audit que même les administrateurs de base de données ne sont pas en mesure de désactiver, falsifient en secret. Par conséquent, la capacité d'audit fournie par le fournisseur du SGBDR doit être la première option. Une autre option serait un lecteur de journal de transactions tiers ou un lecteur de journal personnalisé qui pousse les informations décomposées dans un système de messagerie qui se termine dans certaines formes de Data Warehouse d'audit ou de gestionnaire d'événements en temps réel. En résumé: Solution Architect / «Hands on Data Architect» doit s'impliquer dans la destination d'un tel système en fonction des exigences. Il est généralement trop sérieux de confier la solution à un développeur.

Joël Mamedov
la source
3

Il existe de nombreuses façons de procéder. Ma manière préférée est:

  1. Ajoutez un mod_userchamp à votre table source (celui que vous souhaitez enregistrer).

  2. Créez une table de journal contenant les champs que vous souhaitez consigner, plus un champ log_datetimeet seq_num. seq_numest la clé primaire.

  3. Créez un déclencheur sur la table source qui insère l'enregistrement actuel dans la table du journal chaque fois qu'un champ surveillé est modifié.

Maintenant, vous avez un enregistrement de chaque changement et qui l'a fait.

JosephStyons
la source
Alors ... qu'est-ce que le champ mod_user est censé faire?
conny
1
Dites-vous qui a fait le changement. Le code de mise à jour doit inclure quelque chose pour définir ce champ sur l'utilisateur actuel.
JosephStyons
Et les suppressions, alors? Si vous supprimez une ligne, comment gérez-vous la valeur de la colonne mod_user?
Kenn Cal
Les déclencheurs @KennCal peuvent utiliser des tables virtuelles, vous pouvez voir les données après et avant à l'intérieur du même déclencheur. Peu importe l'opération. stackoverflow.com/questions/6282618/…
Renan Cavalieri
2
@KennCal Vous avez raison, le déclencheur de suppression devra soit stocker ces informations pour vous. Le diable est dans les détails cependant - si vous utilisez l'authentification SQL, le déclencheur peut simplement exécuter [select CURRENT_USER]. S'il s'agit d'une application cliente, le code client doit annoncer de qui il s'agit. S'il s'agit d'un appel d'API, l'utilisateur qui supprime doit être un paramètre obligatoire de l'appel.
JosephStyons
1

Selon le principe de séparation:

  1. Les tables de données d'audit doivent être séparées de la base de données principale. Étant donné que les bases de données d'audit peuvent contenir de nombreuses données historiques, il est logique du point de vue de l'utilisation de la mémoire de les séparer.

  2. N'utilisez pas de déclencheurs pour auditer toute la base de données, car vous vous retrouverez avec un désordre de bases de données différentes à prendre en charge. Vous devrez en écrire un pour DB2, SQLServer, Mysql, etc.

Bhagat007
la source