In einem Projekt, an dem ich arbeite, muss jede Änderung an den Zeilen in einigen Tabellen der Datenbank für eine weitere Prüfung oder ein Rollback nachverfolgt werden . Es muss leicht zu finden sein, wer die Zeile von welcher IP-Adresse und wann geändert hat, und die vorherige Version wiederherstellen können.
Ähnliches wird beispielsweise von Stack Exchange verwendet. Wenn ich die Frage eines anderen ändere, kann ich feststellen, dass ich sie geändert habe, und die Änderungen rückgängig machen.
Mit welcher allgemeinen Technik wird jede Änderung an einem Objekt in einer Datenbank gespeichert , da mein aktuelles Schema im Wesentlichen dieselben Eigenschaften (unten) aufweist wie eine durchschnittliche Geschäftsanwendung?
- Die Objekte sind relativ klein: Es gibt möglicherweise einige
nvarchar(1000)
, aber keine großen Blobs von Binärdaten, die direkt auf der Festplatte gespeichert werden und auf die direkt zugegriffen wird, und nicht über Microsoft SQLfilestream
. - Die Datenbanklast ist ziemlich gering und die gesamte Datenbank wird von einer virtuellen Maschine auf einem Server verwaltet.
- Der Zugriff auf die vorherigen Versionen muss nicht so schnell sein wie der Zugriff auf die neueste Version, muss jedoch aktuell sein¹ und nicht zu langsam².
<tl-dr>
Ich habe über die folgenden Fälle nachgedacht, aber ich habe keine wirklichen Erfahrungen mit solchen Szenarien, daher würde ich die Meinungen anderer hören:
Speichern Sie alles in derselben Tabelle und unterscheiden Sie die Zeilen nach ID und Version. IMO, es ist ernsthaft dumm und wird bald oder später auf Leistungsniveau schaden. Mit diesem Ansatz ist es auch unmöglich, eine andere Sicherheitsstufe für die neuesten Elemente und die Versionsverfolgung festzulegen. Schließlich wäre jede Abfrage komplizierter zu schreiben. Um auf die aktuellen Daten zugreifen zu können, wäre ich gezwungen, alles nach ID zu gruppieren und in jeder Gruppe die letzte Version abzurufen.
Speichern Sie die neueste Version in einer Tabelle und kopieren Sie bei jeder Änderung die veraltete Version in eine andere Tabelle in einem anderen Schema. Der Fehler ist, dass wir jedes Mal jeden Wert speichern, auch wenn er sich nicht geändert hat. Das Setzen von unveränderten Werten auf
null
ist keine Lösung, da ich auch verfolgen muss, wann der Wert zunull
oder von geändert wirdnull
.Speichern Sie die neueste Version in einer Tabelle und die Liste der geänderten Eigenschaften mit ihren vorherigen Werten in einer anderen Tabelle. Dies scheint zwei Fehler zu haben: Der wichtigste ist, dass die einzige Möglichkeit, heterogene Typen vorheriger Werte in derselben Spalte zu sortieren, darin besteht, a zu haben
binary(max)
. Das zweite ist, dass es meiner Meinung nach schwieriger wäre, eine solche Struktur zu verwenden, wenn dem Benutzer die vorherigen Versionen angezeigt werden.Gehen Sie genauso vor wie in zwei vorherigen Punkten, speichern Sie die Versionen jedoch in einer separaten Datenbank. In Bezug auf die Leistung kann es interessant sein, den Zugriff auf die neuesten Versionen nicht zu verlangsamen, indem die vorherigen Versionen in derselben Datenbank gespeichert werden. Dennoch glaube ich, dass dies eine vorzeitige Optimierung ist und nur durchgeführt werden muss, wenn es einen Beweis dafür gibt, dass ältere und neueste Versionen in derselben Datenbank ein Engpass sind.
</ tl-dr>
¹ Es ist beispielsweise nicht akzeptabel, die Änderungen in einer Protokolldatei zu speichern, wie dies bei HTTP-Protokollen der Fall ist, und die Daten nachts aus dem Protokoll in die Datenbank zu löschen, wenn die Serverlast am niedrigsten ist. Die Informationen zu verschiedenen Versionen müssen sofort oder fast sofort verfügbar sein. Eine Verzögerung von einigen Sekunden ist akzeptabel.
² Auf die Informationen wird nicht sehr häufig und nur von einer bestimmten Benutzergruppe zugegriffen. Es wäre jedoch nicht akzeptabel, sie zu zwingen, 30 Sekunden auf die Anzeige der Versionsliste zu warten. Auch hier ist eine Verzögerung von einigen Sekunden akzeptabel.
quelle
Antworten:
Die normale Art der Überwachungsprotokollierung dieser Art besteht darin, eine Schattentabelle zu haben und Änderungen mit Triggern in der Basistabelle zu protokollieren, die Sie überwachen. Die anderen Tabellen können auf einer anderen physischen Festplatte abgelegt werden, wenn dies für die Leistung erforderlich ist, und Sie können Indizes auf sie setzen, wenn Sie das schnelle Abrufen der Daten unterstützen möchten.
Die Tabellen haben ungefähr die gleiche Struktur wie Ihre ursprünglichen Tabellen, jedoch eine Datums- / Uhrzeitspalte für den Zeitpunkt der Änderung und eine Markierung dafür, ob die Zeile eingefügt, geändert oder gelöscht wurde. Die Sequenzierung der Versionen kann über den Zeitstempel erfolgen.
Das Änderungsdatum kann vorgenommen werden, indem die datetime-Spalte mit dem Standardwert getdate () nicht null gemacht wird. Eine Überwachungsbenutzerspalte erfasst den Benutzer mit einer Nicht-Null-Spalte, die standardmäßig Suser_Sname () ist. Angenommen, der tatsächliche Benutzer wird in der Sitzung imitiert, wird die Identität des Benutzers erfasst, der die Änderung vornimmt.
Die Datenbank kann die IP-Adresse, die eine Verbindung zu einem Webserver herstellt, nicht kennen. Die Anwendung muss die IP-Adresse bei der Transaktion explizit erfassen und protokollieren.
Wenn Sie eine große Anzahl von Tabellen haben, die Sie prüfen möchten, können Sie die Trigger mithilfe der Metadaten aus dem Systemdatenwörterbuch programmgesteuert generieren.
Diese Lösung ist aus mehreren Gründen bei weitem die beste:
Es erfasst alle Änderungen an der Tabelle, nicht nur die von der Anwendung vorgenommenen.
Die Überwachungstabellen können auf einem anderen Satz von Datenträgern abgelegt werden, um die E / A-Belastung Ihrer primären Tabellen zu verringern.
Sie können eine Ansicht verwenden, die auf einer Vereinigung der Tabelle und der Überwachungsprotokolltabelle basiert und den gesamten Verlauf einschließlich der aktuellen Version anzeigt.
Sie können die Überwachungsprotokolltabellen nach Bedarf indizieren, damit die Überwachungsbenutzer sie reaktionsschnell abfragen können. Wie üblich ist die Indexauswahl ein Kompromiss zwischen Abfrageleistung und Aktualisierungsaufwand.
quelle
Ich kenne viele CMS-Systeme (einschließlich Wordpress), die eine einzige Tabelle zum Speichern aller Versionen der Daten verwenden. Andererseits müssen sie dies nur für die Tabelle tun, die die Blog-Beiträge enthält. Siehe die Wordpress-Datenbankstruktur .
Auch die Anzahl der Datensätze und die Anzahl der Revisionen, die jede Zeile durchläuft, spielen eine wichtige Rolle bei Ihrer Entscheidung.
quelle
Informationen zur CMS-Versionierung; Für Drupal wird eine spezielle Tabelle für jedes Feld der Entität erstellt, in der der alte Wert gespeichert ist. Ein solches Konzept ermöglicht Ihnen eine Feinmanipulation Ihrer Daten, aber ich denke, es ist teuer. Meine eigene Lösung besteht darin, mein Objekt in das XML-Format zu konvertieren und es als Zeichenfolge mit den anderen Feldern (Änderungszeit, ID ...) zu speichern.
quelle