Entwicklung eines Datenbanksystems

Hi IT-Community,

ich habe eine weitere Frage an euch:

Wie handhabt man "Versionen-Kontrolle"? (Z.B. mit Oracle?)

Es ist so das bei größeren Änderungen am Inhalt (am besten bei allen Änderungen, weil man ansonsten für alle Felder Änderungsmaßstäbe definieren müsste) eine neue Version erstellt werden muss und man auf die ältere immer noch Zugriff haben können muss.

Außerdem sollen immer Reports abgespeichert werden, wenn sich etwas wichtiges während des Signierungs-Prozesses abspielt:

Beispiel: Der Projektleiter schickt den Inhalt zur Signierung raus, dann muss der Inhalt eingefroren werden. Der Signierungs-Prozess dauert gut mal 20 Tage. Und in dieser Zeit darf sich nichts ändern.

Es soll ein Report erzeugt werden, wenn: Der Signierungsprozess von einem Admin abgebrochen wird, der Inhalt genehmigt wurde, der Genehmigungsstatus entfernt wird, und abgelehnt wird. Ausnahme: Wenn der Genehmigungsstatus entfernt wird, soll der alte Report der nach der Genehmigung erstellt wurde einfach mit einem Kommentar des Administrators ergänzt werden.

Wie genau funktioniert das mit Versionen und Reports?
Eigentlich bräuchte ich für jedes Program doch eine eigene Tabelle für Reports (1:m) oder nicht, die jedes mal ergänzt wird.
Und wie handhabt man das mit Versionen? Weil an der Programm-ID darf sich nichts ändern und ich bräuchte ja für eine richtige neue Version eine neue Programm-ID. Legt man dafür dann auch Reports an mit ALLEN Informationen oder gibt es dabei ein spezielles Verfahren?

Grüße
 
Werbung:
Versionierung widerspricht ein wenig der SQL-Idee, jedes Datum genau ein einziges Mal an genau einer Stelle vorrätig zu halten. Die Archivierung kannst Du also nicht einfach aktivieren, sondern hast im Grunde drei Möglichkeiten:
1) Regelmäßige komplette Snapshots der Datenbank
- Eher eine Backup-Lösung, es funktioniert nicht, einen bestimmten Zustand einfach wieder aufzurufen. Für Dich eher ungeeignet.

2) Versionierung in das Datenschema einbauen.
Jede Tabelle enthält nicht nur eine id-Spalte, sondern auch eine revisions-Spalte. Bei jeder Änderung wird für einen Datensatz dann eine neue Zeile mit gleicher id und neuer revisions-nummer angelegt. PK ist dann (id, rev_nr) . Beispiel:

id | rev_nr | produkt | farbe
89 | 1 | Porsche | schwarz
90 | 1 | VW Polo | grün
91 | 1 | VW Polo | blau
91 | 2 | VW Polo | schwarz
92 | 1 | VW Golf | blau
Es gibt hier also vier verschiedene Autos. Eines davon, der VW Polo in blau wurde aber umgespritzt und die Farbe wurde geändert.

Ein Update eines Datensatzes würde in Insert mit inkremnetierter rev_id umgeschrieben und der UPDATE-Befehl würde generell für alle Tabellen verboten. Du hast mit dieser Lösung somit einen viel höheren Speicherplatzverbrauch, was wohl unproblematisch ist, aber fast alle Abfragen müssen ein "SELECT ... MAX(rev_nr) ... GROUP BY id" enthalten, damit Du jeweils die aktuelle Version bekommst. Der Aufwand für die komplette Datenverarbeitung steigt also wahrnehmbar. Es dürfte aber eine geeignete Lösung für Dein ja eher kleineres Projekt sein.

3) Eine weitere Möglichkeit wäre eine Archiv-Tabelle mit einer Datenspalte, die alle Tabelleneinträge aufnehmen kann (hstore, json). Mit etwas Mehraufwand lassen sich die jeweiligen Werte daraus wieder auslesen. Dann muss in jede Tabelle ein Trigger eingefügt werden, der die Daten bei Veränderung dahin kopiert. Der Vorteil liegt darin, dass Dein Datenmodell unangetastet bleibt. Der Nachteil ist die komplexere Abfrage, um die passenden Archiv-Daten aus der DB zu holen.
Ich habe das in PostgreSQL realisiert:
https://www.datenbankforum.com/thre...new-spalte-mit-variablem-namen-auslesen.2621/
Dort findest Du auch zwei Links zu ähnlichen Umsetzungen und kannst einen Eindruck gewinnen, wie man das realisieren kann.

Vielleicht hast Du Glück und Oracle bietet so etwas direkt als Feature an. Ansonsten würde ich die Warnung aussprechen, dass das vielleicht zwar nicht High-End-Datenbanken-Design ist, aber ich habe beispielsweise zwei Wochen an meiner Archivierungsfunktion gesessen. Du musst entweder Dich in Trigger einarbeiten oder Dein ganzes DB-Design sorgfältig um die Archivierungsfunktion erweitern und in Zukunft alle generierten Abfragen passend ergänzen. Beides wird dauern.

Für Deine Reports würde sich wohl am ehesten die Archiv-Tabelle eignen. Für die Versionierung wohl die zweite Variante. Das Einfrieren ließe sich über eine extra Signierungs-Tabelle lösen, indem die Werte mit ihren zugehörigen IDs fest gespeichert werden. Würde eine Versionierung wie oben beschrieben in die Tabelle eingebaut werden, dann würde auch die Speicherung der id und rev_id reichen. Es gibt ja keine Änderungen an den Daten.
 
Zuletzt bearbeitet:
In diesem Fall macht eine Archiv-Tabelle wirklich wenig Sinn...
Eine passende Partitionierung, die über eine Hilfsspalte (Boolean, 0/1, o.ä.) die nur den Status archiviert(Veraltet) bzw. nicht archiviert(Neu) darstellt gelegt ist, dürfte die sinnvollere Variante sein...
 
Zuletzt bearbeitet:
Danke für die Antwort. Hilft mir weiter!

Aber ich dachte mir im Thema Signierung so etwas:
Einen "Overall"-Report erstellen, der eine Zusammenfassung der wichtigsten Daten enthält, den man betrachten kann und signieren kann.
Also, wenn man meinen "genehmigungs-thread" betrachtet, praktisch an der stelle für "Referenz zu dokument", der "Overall-Report" aufgenommen wird.

Das müsste doch auch klappen oder?

===

Aber deine letzte Lösung mit der Boolean-Spalte verstehe ich nicht ganz. Ich habe jeden Datensatz zwei mal und eine Boolean-Variable (alt/neu), die bei jeder Änderung sofort den neuen auf alt setzt und dann wird einfach alles was "alt" ist rausgefiltert?

===

Noch was:
Haben die "großen" DBMS nicht ein Transaktionslog, das alle Änderungen anzeigt und wiederherstellen lässt?
 
Zuletzt bearbeitet:
Haben die "großen" DBMS nicht ein Transaktionslog, das alle Änderungen anzeigt und wiederherstellen lässt?
Das stellst du dir ganz falsch vor... Besonders wenn Revisionierung und Reporting sich kennenlernen wird es da ein Problem geben :)

Zu meiner Hilfsspalte: Die müsste dann natürlich von deiner Businesslogik bearbeitet werden...
Prozeduraler Ablauf in etwa so:

1. Person will neuen Datensatz anlegen
2. Routine sucht nach bestehendem gültigen Datensatz anhand des Primärschlüssel
- Möglichkeit A: Findet einen bestehenden Datensatz. Setzt die Revision = (höchste gefundene Revision + 1), Gültigflag = TRUE
- Möglichkeit B: Findet keine Daten. Setzt die Revision = 1, Gültigflag = TRUE
3. Ganz viel Prüfungslogik... Passen die angegeben Daten, ist der Mitarbeiter überhaupt noch bei uns..., etc.
4. Neuen Datensatz einfügen.
-Möglichkeit A: Eine Exception wird von deinen Constraints geschmissen (hoffentlich nicht, aber grundsätzlich Möglich)
-Möglichkeit B: Alles gut.
Nur wenn Möglichkeit B zutrifft:
5. den alten Datensatz bearbeiten mit Gültigflag = FALSE

Lässt jetzt zwar erstmal sämtliche concurrency außer Acht... (D.h. diverse Locks sind nicht beschrieben) Aber das Wissen setze ich jetzt einfach mal vorraus wenn man sich an so ein Projekt ranwagt :)

Edit: Der einzige Sinn und zweck davon ist, das die Daten in der gleichen Tabelle liegen (also Reporting über alle Revisionen ermöglichen), es aber keine Performanceeinbußen durch Datenmasse gibt... Da sie eben in einer separaten Partition liegen und nur angesprochen werden wenn man sie wirklich will...
 
Ah ich verstehe. Also deine zuerst genannte Möglichkeit 2) in Verbindung mit Alt/Neu flag, um alles alte einfach ausblenden zu können und an einem anderen Speicherort ablegen.

Und das ganze funktioniert dann so in etwa oder (?) :

CREATE TABLE ...
PARTITION BY RANGE ( Gültigflag)
(PARTITION Program_Revision VALUES false TABLESPACE Speicherort1,
(PARTITION Program VALUES true TABLESPACE Speicherort2,
...);

Bei Program_Revision sollten dann alle Ergebnisse mit rev_nr liegen die eins kleiner als die aktuelle ist.
So in etwa oder?
 
@Säsch Du brauchst eine Partition nur dann, wenn die Datenmenge dieser Tabelle entsprechend groß ist. Sollen die Chefs Milliarden Projekte absegnen? Erst dann würde die Tabellengröße so anschwellen, dass man sich Gedanken über Partitionierung machen sollte. Für ein paar Tausend Projekte ist Partitionierung nicht relevant. Da reicht dann ein boolesches Feld (wenn Du nur zwei Varianten hast) oder eine rev_nr-Variante (wenn Du beliebig viele Änderungen durchführen möchtest). Beides zusammen brauchst Du natürlich nicht, da sich der boolesche Wert aus der rev_nr errechnen lässt.

Ich verstehe Deinen Report-Ansatz noch nicht. Sollen in der DB einfach irgendwelche Datensätze als zu einem Report gehörend markiert werden oder willst Du eine Zusammenstellung aller Werte in einer extra Struktur haben (PDF-Dokument, extra Tabelle, ...)? Ich empfehle Dir die zweite Variante: Die Leute bekommen eine übersichtliche Dokumentation und wenn sie auf sign klicken, laufen in der Datenbank die entsprechenden Aktualisierungen. Du musst also die relevanten Datensätze in ihrem Ist-Zustand zusammenstellen und einfrieren. Wenn Du eine gleichförmige Struktur hast, kannst Du eine extra Tabelle schreiben, in etwa so:
id | tab_a_id | tab_a_projekt_spalte | tab_a_verantwortlich_spalte | tab_b_id | tab_b_kunde_spalte | ...
Alle relevanten Datensätze werden in dieser Tabelle zusammengeführt. Wenn Du beispielsweise mehrere Kunden hast, würden alle in ein Datenfeld geschrieben. Beispielsweise mit einem hstore- oder json-Feld oder einer einfachen Konkatenation. Wenn die Tabellen, die Du einem Report speichern musst, sich aber ändern, dann ist eben eine Tabelle mit einem einzigen Datenfeld, im hstore oder json-Format die beste Variante, weil es weiterhin durchsuchbar ist und Du die Daten auch einzeln wieder abrufen kannst. Siehe dafür meinen Punkt 3.
 
Du brauchst eine Partition nur dann, wenn die Datenmenge dieser Tabelle entsprechend groß ist. Sollen die Chefs Milliarden Projekte absegnen? Erst dann würde die Tabellengröße so anschwellen, dass man sich Gedanken über Partitionierung machen sollte. Für ein paar Tausend Projekte ist Partitionierung nicht relevant. Da reicht dann ein boolesches Feld (wenn Du nur zwei Varianten hast) oder eine rev_nr-Variante (wenn Du beliebig viele Änderungen durchführen möchtest). Beides zusammen brauchst Du natürlich nicht, da sich der boolesche Wert aus der rev_nr errechnen lässt.
Ich glaube hier kollidieren gerade Grundsätze...
Die Partitionierung ist nicht nur für große Datenmengen gedacht. Das ganze zieht dann auch einen Rattenschwanz an Back-Up, Datenwiederherstellung, Indizierung, Informationsbereitstellung für die DB, etc. mit sich...
 
@Tom: Ja ich dachte daran alle Report-Daten in einer oder mehreren Tabellen "Reports" zu speichern.

Da ich mich in der Konzeptphase befinde bin ich für jede eurer Informationen dankbar. Tom und Distrilec danke für eure Vorschläge. Ich sollte beides Ansprechen am Ende entscheidet das Management: Entweder mit Partitionierung oder Ohne: Mehr Geschwindigkeit vs weniger Entwicklungsaufwand, einfachere Abfragen, etc...
 
Mehr Geschwindigkeit vs weniger Entwicklungsaufwand, einfachere Abfragen, etc...
Hier gibt es kein "vs.".... Mit Partitionierung hast du beides ;) Da du nunmal nur eine Tabelle, statt zwei hast :) Zusätzlich musst du mit meiner Hilfsspalte nicht immer den neusten Datensatz "berechnen" (sei wohl ein verziehener Normalisierungsfehler...Normalisierung ist eben nur in der Theorie immer einzuhalten, besonders seitdem Plattenplatz so billig geworden ist... Und die 1-2 MB seien mir dann verziehen)
 
Ich glaube hier kollidieren gerade Grundsätze...
Die Partitionierung ist nicht nur für große Datenmengen gedacht. Das ganze zieht dann auch einen Rattenschwanz an Back-Up, Datenwiederherstellung, Indizierung, Informationsbereitstellung für die DB, etc. mit sich...

Ja, eben. Die Partitionierung würde einen Rattenschwanz nach sich ziehen, der unnötig ist für eine Datenbank, die wahrscheinlich nie größer als 100 MB sein wird. Eine Partitionierung ist doch nichts anderes als eine Aufteilung der Daten unter der Haube, oder bin ich da nicht up to date? Wo liegt denn da der Vorteil, wenn es nicht um große Datenmengen geht? Backups aufspalten ist ein gewagtes Unterfangen und auch nur dann möglich, wenn sich die alten Daten definitiv nicht mehr ändern. Bei einer 2000 Mann Firma, würde ich dann doch eher den zusätzlichen Plattenplatz anfordern, als das Risiko einzugehen, später nur zerschossene Backups zu haben.

Entweder mit Partitionierung oder Ohne: Mehr Geschwindigkeit vs weniger Entwicklungsaufwand, einfachere Abfragen, etc...
Das ist falsch: Du hast ja Indizes auf den Spalten. Die Geschwindigkeit ist also bei kleineren Datenbanken identisch. Eine Partitionierung ist dann ein Vorteil, wenn z. B. die aktuelle Partition in den Hauptspeicher passt, die gesamte Tabelle dies aber nicht würde. Dann hättest Du einen Geschwindigkeitsvorteil. Aber das Problem sehe ich bei Deiner Tabelle nicht, es wird doch nicht über die Größenordnung von einigen Tausend Projekten hinausgehen. Und selbst wenn es das tut, kannst Du Dich dann immer noch um Partitionierung kümmern und die DB anpassen. Jetzt in dieser Phase scheint mir das aber eine irrelevante Frage zu sein. By the way, Du kannst die Tabelle nach beliebigen Kriterien partitionieren, d. h. Du benötigst dafür kein boolesches Feld.

Hier gibt es kein "vs.".... Mit Partitionierung hast du beides ;) Da du nunmal nur eine Tabelle, statt zwei hast :) Zusätzlich musst du mit meiner Hilfsspalte nicht immer den neusten Datensatz "berechnen"
Deine Hilfsspalte muss halt aktuell gehalten werden mit den entsprechenden Fehlerquellen. Im Kern wäre Deine Hilfsspalte aber doch nur der Versuch, die Abfragen schneller zu machen, eine rev_nr würdest Du ja auch brauchen. Und da hätte ich genug Vertrauen in Oracle, dass ein "Berechnen", sprich ein Max(rev_nr), sich faktisch genauso schnell holen lässt wie ein boolescher Wert. Vorausgesetzt man hat einen zusammengesetzten Index auf (id, rev_nr). Nur bei mehreren Revisionseinträgen hätte man unwesentlich mehr Indexabfragen, als bei einem zusammengesetzten Index auf (id, Gültigflag).
 
Ja, eben. Die Partitionierung würde einen Rattenschwanz nach sich ziehen, der unnötig ist für eine Datenbank, die wahrscheinlich nie größer als 100 MB sein wird. Eine Partitionierung ist doch nichts anderes als eine Aufteilung der Daten unter der Haube, oder bin ich da nicht up to date? Wo liegt denn da der Vorteil, wenn es nicht um große Datenmengen geht? Backups aufspalten ist ein gewagtes Unterfangen und auch nur dann möglich, wenn sich die alten Daten definitiv nicht mehr ändern. Bei einer 2000 Mann Firma, würde ich dann doch eher den zusätzlichen Plattenplatz anfordern, als das Risiko einzugehen, später nur zerschossene Backups zu haben.
1. Partitionierung erlaubt es eine Tabelle in verschiedenen Tablespaces (ja, sogar Datafiles) zu kippen... (Um die teuren SSDs nicht so zu belasten)
2. Wenn es wirklich mal ein Datenausfall geben sollte ist es besonders wichtig den alten Stand so schnell wie möglich wieder einzuspielen... Bester Weg? Das "unwichtige" vom "wichtigen" trennen. Also erstmal nur die aktuellen Revisionen einspielen... Wenn die veralteten erst ne Stunde später wieder verfügbar sind, ist das wohl kein Beinbruch :)
Das ist ziemlich simpel (zumindest in Oracle) in dem man einfach ein anderes Tablespace für die "unwichtige" Partition gibt... (Man könnte sogar über einen Zeitraum gehen und sagen alle Revisionen älter zwei Jahre müssen nichtmehr gesichert sein...) (Das sollte eigentlich durchgehend für alle Tabellen gemacht werden, sofern möglich... Ist allerdings auch mehr Administrationsaufwand... Der Kosten/Nutzen-Faktor steigt also, je mehr Daten man hat)

3.Performance (auch wenn es in absehbarer Zeit nicht wirklich schlimm sein sollte... Du weißt nicht wie große seine Firma ist ;) Und wenn man einfach mal so diverse Oracle/MS SQL DBs bereitstehen hat... Muss es etwas größeres sein :) )

4. Besser haben und nicht brauchen, als brauchen und nicht haben... Etwas nicht zu tun, nur weil man es DERZEIT nicht braucht, ist nie wirklich sinnvoll...
 
@Distrilec Ich finde alle Deine Argumente pro Partitionierung ja richtig. Nur geht es um eine Firma mit 2000 Leuten, wenn da die SSD für 800 Euro das Konzept für eine Datenbank bestimmt, sollte sie einen Insolvenzverwalter beauftragen. Auch geht es um Tabellen mit eher Tausenden als Millionen Einträgen, da sind Gedanken um Partitionierung vergeudete Zeit. Zudem ließe sich Partitionierung auch nachträglich hinzufügen. Auch handelt es sich nicht um eine systemkritische Datenbank, wie viele Minuten das Backup einspielen dauert, ist da egal. Zudem bin ich mir nicht sicher, ob in der Firma die nötige Kompetenz vorhanden ist, ein Backup abschnittsweise einzuspielen.
Und, das ist mein Hauptpunkt, hier soll jemand ein Konzept erarbeiten, der gerade in drei Monaten eine Bachelor-Arbeit schreibt. Will er das schaffen, muss er sich auf das Wesentliche konzentrieren und Partitionierung gehört in seinem Fall nicht dazu. Würde er ein Data Warehouse konzipieren, hättest Du mit allem recht, solange es aber nicht danach aussieht, dass in der Datenbank Milliarden Einträge stehen werden, sollte er sich in seiner knappen Zeit nicht mit Partitionierung aufhalten.
 
Werbung:
Ja, richtig... Aber genug davon... Grundsatzdiskussionen helfen ihm da wirklich nicht... Ich denke er hat beide Seiten verstanden, was er macht sei dann ihm bzw. der übergeordneten Macht überlassen...
 
Zurück
Oben