Was genau willst du versionieren? Das Schema oder die Daten?
Tdammers
1
Ich möchte die Daten versionieren. Um am Beispiel von cms zu bleiben, lassen Sie uns die Versionen von Artikeln sagen .
Matcauthon
Vielleicht möchten Sie sich mit Datomic befassen.
Dan_waterworth
Antworten:
19
Grundsätzlich gibt es zwei Ansätze: Eine Prüftabelle mit allen zuvor gespeicherten Werten oder einem Start- / Enddatum als Teil der Tabelle. Bei allen Aktualisierungen wird ein neuer Datensatz erstellt, während der alte Datensatz geschlossen wird.
Der erste Ansatz ist also möglicherweise skalierbarer. Da auf die "archivierten" Daten selten zugegriffen wird, könnte das Datenbankdesign optimiert werden. Und der Arbeitstisch bleibt klein. Je nach Komplexität sollte es auch möglich sein, nur Unterschiede zu speichern. Ist es ratsam, das Erinnerungsmuster zu verwenden ?
matcauthon
1
Dies hängt von Ihrer Verwendung ab. Möglicherweise reicht es aus, Trigger zum Auffüllen der Tabelle (n) zu verwenden und dann festzulegen, wie und wie weit ein Rollback durchgeführt werden soll.
Jmoreno
Sie haben einen Tippfehler in Ihrer Antwort (Muster sollte Muster sein)
Geocodezip
7
Eine Idee ist die Verwendung von "Nur-Einfügen-Datenbanken". Die Grundidee ist, dass Sie niemals Daten in einer Zeile löschen oder aktualisieren .
Jede zu verfolgende Tabelle hat zwei datetimeSpalten fromund to. Sie beginnen jeweils mit dem Wert NULL(Beginn bis Ende der Zeit). Wenn Sie die Zeile "ändern" müssen, fügen Sie eine neue Zeile hinzu und aktualisieren gleichzeitig die toin der vorherigen Zeile auf Nowund die fromin der Zeile, die Sie hinzufügen Now.
Leider scheint diese Frage gelöscht worden zu sein :(
Douglas Gaskell
Kein Problem, hier ist der Link . Ein weiterer guter Designvorschlag im Link
EL Yusubov
2
Ich denke, Sie können Trigger für jede Tabelle verwenden und die Daten in _history pflegen (oder Sie können einen beliebigen Namen vergeben), und bei jedem Einfügen, Aktualisieren, Löschen in der Haupttabelle wird Ihr Trigger ausgelöst, und Sie können die Details in dieser Tabelle speichern ist auch mit SQLite-Datenbank verfügbar, wenn Sie eine verwenden.
Dieser Mechanismus ist auch für große Projekte nützlich. In dieser Tabelle können Sie die Informationen des Benutzers, der die Änderungen vorgenommen hat, zusammen mit dem Zeitstempel der Änderungen protokollieren. Anschließend können Sie Ihre Tabelle mit einem beliebigen Zeitstempel wiederherstellen, der Ihren Anforderungen entspricht.
Jede Datenbank hat ihre eigene Art, Trigger zu schreiben und zu codieren. Wenn Sie SQLite verwenden, besuchen Sie SQLite.org für die Syntax. Für andere Datenbanken können Sie ihre offiziellen Websites besuchen.
Sie kennen wahrscheinlich die SQLite-Datenbank- Engine. Die gesamte Datenbank wird in einer einzigen Datei gespeichert. Die API unterstützt auch virtuelle Dateisysteme, sodass Sie den Speicher grundsätzlich überall und in jedem Format organisieren können. Reagieren Sie einfach auf Lese- und Schreibvorgänge bei bestimmten Datei-Offsets. Mögliche Anwendungen hierfür könnten Verschlüsselung, Komprimierung usw. sein. Das Beste daran ist, dass die Containerebene nichts über Datenbanken, SQL- oder SQLite-Dateiformate wissen sollte. Befolgen Sie einfach xRead- und xWrite-Rückrufe.
Eine der Ideen war die Implementierung von Zeitmaschinenfunktionen. Jede xWrite-Operation speichert also jedes Segment, das sie überschreiben würde, in der "Rückgängig" -Historie und der Benutzer kann ein Datum in der Vergangenheit auswählen, um zu sehen, was die Datenbank enthielt (wahrscheinlich schreibgeschützt). Ich habe noch kein funktionierendes Beispiel (es gab eine Diskussion darüber bei sqlite mail list), aber wahrscheinlich liefern andere Engines VFS-APIs, so dass etwas Ähnliches möglich ist. Und sobald es implementiert ist, sollte es mit Datenbankstrukturen beliebiger Komplexität kompatibel sein.
Was denken Sie, ist dieser Ansatz für größere Projekte skalierbar?
matcauthon
Ich denke, dies könnte einen hohen Datenaufwand für große Datenänderungen bedeuten (offensichtlich, da jede einzelne Änderung gespeichert werden sollte, obwohl die Komprimierung für ältere Versionen hilfreich sein kann). Abgesehen von dem Punkt, den Sie in Ihrem Schema haben, funktioniert es für zwanzig, solange es für zwei Tabellen funktioniert.
Maksee
1
Bei der Versionierung von Datenbankeinträgen wird eine Überwachungstabelle verwendet. Die Tabelle enthält ein Schema wie folgt:
Seq - Int ' Unique identifier for this table
Event - Char ' Insert / Update / Delete
TblName - Char ' Table that had field value changed
FldName - Char ' Field that was changed
KeyValue - Char ' delimited list of values for fields that make up the PK of table changed
UsrId - Char ' User who made the change
OldValue - Char ' Old value (converted to character)
NewValue - Char ' New value (converted to character)
AddTs - DateTime ' When the change was made
Wir haben dann Trigger beim Einfügen / Aktualisieren / Löschen der Tabellen, die wir verfolgen möchten.
Vorteile:
Alle Daten befinden sich in einer Tabelle
Kann so eingerichtet werden, dass alle Felder oder bestimmte Felder in einer Tabelle nachverfolgt werden
Einfache Anzeige der Versionierung für jedes Feld einer Tabelle
Nachteile:
Alle Überwachungsinformationen in einer Tabelle zu haben, führt zu einer extrem großen Anzahl von Datensätzen
Ich mache jetzt eine Version davon. Für jeden Datensatz habe ich ein Boolesches Flag für Einfügungsdatum, Änderungsdatum und aktiven Datensatz. Für die anfängliche Einfügung werden das eingefügte und das geänderte Datum auf Now () gesetzt (in diesem Beispiel in Access) und das Flag für aktive Datensätze auf true. Wenn ich dann diesen Datensatz ändere, kopiere ich das Ganze in einen neuen Datensatz, ändere die Felder, die der Benutzer ändert, lasse das Einfügedatum gleich dem Original und ändere das Änderungsdatum auf Jetzt (). Ich drehe dann das Active Record Flag des Originaldatensatzes auf falseund den neuen Datensatz auf true. Ich habe auch ein Feld für ModifiedRecordsParentID, in dem ich die Identität des ursprünglichen Datensatzes speichere.
Wenn ich dann noch Fragen stellen muss, kann ich nur Datensätze zurückgeben, bei denen ActiveRecord = trueich nur die aktuellsten Informationen erhalte.
Keine Notwendigkeit für die ActiveRecordFlagge. Die Zeile MAX (*) sollte immer der aktuelle Datensatz sein. Beim Wiederherstellen einer früheren Version wird diese Zeile einfach erneut in die Tabelle eingefügt.
Invertzucker
Ich war mir nicht sicher, wie ich die Auswahl zum Laufen bringen sollte, aber jetzt, wo Sie das ausrufen, denke ich darüber nach und habe eine Idee, hmmmm
Brad
Normalerweise wählt MAX (Spaltenname) den größten Wert in der Tabellenspalte. Um die gesamte Zeile auszuwählen, genügt ein einfacher select top 1 order by id descendingBefehl.
Invertzucker
Ja, das funktioniert für einen einfachen einzelnen Datensatz, aber meine Tabelle war eine Sammlung von untergeordneten Datensätzen, die sofort ausgewählt werden müssten, aber einzeln geändert werden könnten. Nur ein bisschen komplexer.
Antworten:
Grundsätzlich gibt es zwei Ansätze: Eine Prüftabelle mit allen zuvor gespeicherten Werten oder einem Start- / Enddatum als Teil der Tabelle. Bei allen Aktualisierungen wird ein neuer Datensatz erstellt, während der alte Datensatz geschlossen wird.
Update: SQL Server 2016 unterstützt dies als Entwurfsmuster / Tabellentyp - https://docs.microsoft.com/en-us/sql/relational-databases/tables/temporal-tables?view=sql-server-2017
quelle
Eine Idee ist die Verwendung von "Nur-Einfügen-Datenbanken". Die Grundidee ist, dass Sie niemals Daten in einer Zeile löschen oder aktualisieren .
Jede zu verfolgende Tabelle hat zwei
datetime
Spaltenfrom
undto
. Sie beginnen jeweils mit dem WertNULL
(Beginn bis Ende der Zeit). Wenn Sie die Zeile "ändern" müssen, fügen Sie eine neue Zeile hinzu und aktualisieren gleichzeitig dieto
in der vorherigen Zeile aufNow
und diefrom
in der Zeile, die Sie hinzufügenNow
.Weitere Informationen finden Sie unter:
Diese Technik wird
AuditTrail
zum Verwalten von Altdaten aufgerufen und speichert sozusagen den Änderungsverlauf.Es sieht so aus, als ob eine Frage dieser Art bereits veröffentlicht wurde:
quelle
Ich denke, Sie können Trigger für jede Tabelle verwenden und die Daten in _history pflegen (oder Sie können einen beliebigen Namen vergeben), und bei jedem Einfügen, Aktualisieren, Löschen in der Haupttabelle wird Ihr Trigger ausgelöst, und Sie können die Details in dieser Tabelle speichern ist auch mit SQLite-Datenbank verfügbar, wenn Sie eine verwenden.
Dieser Mechanismus ist auch für große Projekte nützlich. In dieser Tabelle können Sie die Informationen des Benutzers, der die Änderungen vorgenommen hat, zusammen mit dem Zeitstempel der Änderungen protokollieren. Anschließend können Sie Ihre Tabelle mit einem beliebigen Zeitstempel wiederherstellen, der Ihren Anforderungen entspricht.
Jede Datenbank hat ihre eigene Art, Trigger zu schreiben und zu codieren. Wenn Sie SQLite verwenden, besuchen Sie SQLite.org für die Syntax. Für andere Datenbanken können Sie ihre offiziellen Websites besuchen.
quelle
Sie kennen wahrscheinlich die SQLite-Datenbank- Engine. Die gesamte Datenbank wird in einer einzigen Datei gespeichert. Die API unterstützt auch virtuelle Dateisysteme, sodass Sie den Speicher grundsätzlich überall und in jedem Format organisieren können. Reagieren Sie einfach auf Lese- und Schreibvorgänge bei bestimmten Datei-Offsets. Mögliche Anwendungen hierfür könnten Verschlüsselung, Komprimierung usw. sein. Das Beste daran ist, dass die Containerebene nichts über Datenbanken, SQL- oder SQLite-Dateiformate wissen sollte. Befolgen Sie einfach xRead- und xWrite-Rückrufe.
Eine der Ideen war die Implementierung von Zeitmaschinenfunktionen. Jede xWrite-Operation speichert also jedes Segment, das sie überschreiben würde, in der "Rückgängig" -Historie und der Benutzer kann ein Datum in der Vergangenheit auswählen, um zu sehen, was die Datenbank enthielt (wahrscheinlich schreibgeschützt). Ich habe noch kein funktionierendes Beispiel (es gab eine Diskussion darüber bei sqlite mail list), aber wahrscheinlich liefern andere Engines VFS-APIs, so dass etwas Ähnliches möglich ist. Und sobald es implementiert ist, sollte es mit Datenbankstrukturen beliebiger Komplexität kompatibel sein.
quelle
Bei der Versionierung von Datenbankeinträgen wird eine Überwachungstabelle verwendet. Die Tabelle enthält ein Schema wie folgt:
Wir haben dann Trigger beim Einfügen / Aktualisieren / Löschen der Tabellen, die wir verfolgen möchten.
Vorteile:
Nachteile:
quelle
Ich mache jetzt eine Version davon. Für jeden Datensatz habe ich ein Boolesches Flag für Einfügungsdatum, Änderungsdatum und aktiven Datensatz. Für die anfängliche Einfügung werden das eingefügte und das geänderte Datum auf Now () gesetzt (in diesem Beispiel in Access) und das Flag für aktive Datensätze auf
true
. Wenn ich dann diesen Datensatz ändere, kopiere ich das Ganze in einen neuen Datensatz, ändere die Felder, die der Benutzer ändert, lasse das Einfügedatum gleich dem Original und ändere das Änderungsdatum auf Jetzt (). Ich drehe dann das Active Record Flag des Originaldatensatzes auffalse
und den neuen Datensatz auftrue
. Ich habe auch ein Feld für ModifiedRecordsParentID, in dem ich die Identität des ursprünglichen Datensatzes speichere.Wenn ich dann noch Fragen stellen muss, kann ich nur Datensätze zurückgeben, bei denen
ActiveRecord = true
ich nur die aktuellsten Informationen erhalte.quelle
ActiveRecord
Flagge. Die Zeile MAX (*) sollte immer der aktuelle Datensatz sein. Beim Wiederherstellen einer früheren Version wird diese Zeile einfach erneut in die Tabelle eingefügt.select top 1 order by id descending
Befehl.Wenn Sie ALLE Änderungen im Laufe der Zeit in der Datenbank speichern möchten, können Sie die Protokollierung auschecken ( /programming/3394132/where-can-i-find-the-mysql-transaction-log) )
quelle