Donnerstag, 24. Mai 2012


Artikel

Oktober 2009 | Artikel

Historisierung mit Oracle und Hibernate

(Link zum Artikel: http://www.entwickler-magazin.de/jaxenter//002621)

Text: Sascha Möllering
  • Teilen
  • kommentieren
  • empfehlen
  • Bookmark and Share
Die meisten Datenbanken enthalten lediglich aktuelle Datensätze. Wird eine Datenbankzeile modifiziert, so wird der dazugehörige Datensatz aktualisiert oder gelöscht. Der Zustand vor der Modifikation des Felds kann nicht mehr hergestellt werden. Für einige Anwendungsfälle ist es jedoch zwingend notwendig, auf den Datenbestand vor der Datenänderung zuzugreifen. Der Datensatz muss also vor der Modifikation gesichert werden. Dieser Artikel zeigt, wie eine Historisierung und die Nutzung der historisierten Daten – auf Basis von einer Oracle-Datenbank und Hibernate – implementiert werden kann.
Teil 1   Teil 2   Teil 3   Teil 4   

Der Begriff "Historisierung" (auch temporale Datenhaltung genannt) bezeichnet das Festhalten des zeitlichen Verlaufs von Daten in einer Datenbank. Eine Historisierung ermöglicht es, festzustellen, welcher Wert zu welchem Zeitpunkt gültig war oder gültig werden wird (zusätzliche Dimension der Datenhaltung). Dabei unterscheiden wir zwischen Transaktionszeit und Gültigkeitszeitraum:

  • Transaktionszeit: Der Zeitpunkt, an dem eine Zeile in die Tabelle eingefügt wurde (Beispiel: Ein Preis für Produkt A wurde am 31.05.2009 eingetragen).
  • Gültigkeitszeitraum: Der Zeitraum, in dem die eingefügte Zeile gültig ist (Beispiel: Ein Preis für Produkt A gilt nur vom 31.05.2009 bis zum 30.06.2009).

Beispiel herunterladen

Das Beispiel zum Artikel im Zip-Format gibt es hier.

In einigen Anwendungsfällen sind beide zeitlichen Betrachtungen relevant. Dann sprechen wir von einer "bitemporalen" Historisierung.

Zusätzlich wird bei der Historisierung zwischen Zeit- und Ereignissteuerung unterschieden. Bei der zeitgesteuerten Variante wird der aktuelle Datenbestand (entweder vollständig oder ein Delta zum zuletzt historisierten Bestand) zu einem Zeitpunkt (meist in der Nacht durch einen Batch-Job) historisiert. Bei der Ereignissteuerung wird bei jeder Datenänderung (insert, update, delete) der zu modifizierende Datensatz (meist mit Modifikationskennzeichen) in den historischen Stand eingefügt. Das bedeutet, dass der aktuelle Datenbestand bei dieser Variante permanent zweimal in der Datenbank vorhanden ist: zum einen im aktuellen und zum anderen im historischen Datenbestand. Aktuelle und historische Daten sollten sinnvollerweise in unterschiedlichen Tabellen gehalten werden, da sonst die Übersichtlichkeit leidet.

Der ereignisgesteuerte Ansatz wird sinnvollerweise mit so genannten "Datenbanktriggern" (im Folgenden "Trigger" genannt) umgesetzt. Ein Trigger ist ein PL-/SQL-Programm, das innerhalb der Datenbank bei (bzw. vor oder nach) bestimmten Operationen wie insert, update oder delete ausgeführt wird. In diesen Programmen sind Informationen, z. B. der alte und neue Wert einer Spalte bei einer Datensatzaktualisierung vorhanden. Mit diesen Informationen ist es möglich, den Stand vor der Aktualisierung in eine andere Tabelle zu schreiben. Es ist zu beachten, dass ein Trigger nur einmal pro Aktion "feuert", d. h. eine Massenoperation über mehr als einen Datensatz ist mit Triggern nicht möglich, da lediglich ein Datensatz historisiert wird.

Der "ereignisorientierte Ansatz" und der Aufbau sowie die Arbeitsweise der Trigger soll im Folgenden anhand eines Cases aus dem Automotive-Bereich erklärt werden:

Wir betrachten ein Händlerportal, beim dem untertags Daten wie z. B. Preise oder Ersatzteile geändert werden können. Da bei Vertragsabschluss unter Umständen andere Werte gültig sind als drei Stunden später, muss eine ereignisgesteuerte Historisierung implementiert werden.

Teil 1   Teil 2   Teil 3   Teil 4   

Kommentare

Gravatar Dirk 04.11.2009
um 08:13 Uhr
Schöne und einfache Lösung. Für komplexere Szenarien greift man am besten zu Envers (http://www.jboss.org/envers/) #zitieren
Gravatar Sascha Möllering 28.11.2009
um 16:51 Uhr
@Dirk: Envers ist absolut sinnvoll, wenn man in einer "pure Java"-Umgebung bleiben kann, wir hatten das Problem, dass - neben der Java-App - auch ETl-Prozesse die Tabellen gefüllt haben, deswegen brauchten wir diese Lösung. #zitieren
Gravatar Raphi 04.12.2009
um 07:45 Uhr
Warum wurde diese Variante ausgewählt und nicht Oracle Flashback ? Weil Hibernate noch nicht Oracle Flashback unterstützt? #zitieren
Gravatar Sascha Möllering 04.12.2009
um 09:38 Uhr
@Raphi Mit Oracle-Flashback wäre das noch deutlich komplizierter geworden, ausserdem wollte der Kunde nur eine "plain" Oracle-DB einsetzen. #zitieren
Gravatar Xenofon Grigoriadis 09.03.2010
um 16:46 Uhr
Was die Modellierung der History-Tabelle angeht, bin ich 100% einverstanden. Allerdings...

als Oracler stehen mir bei Triggern, die sogar "automagisch" angelegt werden, die restlichen Haare zu Berge...
Habe erlebt, dass ein System komplett unwartbar geworden war, weil irgendwann nur noch mit Triggern Business-Logik durch die Hintertür implementiert wurde. Weiß, dass dies hier nicht beabsichtigt wird, ... aber wenn breite Anwendung von Triggern zur Architektur erklärt wird, dann sehe ich schwarz. Es ist eben äußerste Disziplin gefragt... Ich erlebe gerade bei Hibernate-Oracle Architekturen, dass Trigger verwendet werden, um mal eben, Dinge on-the-fly (auf die Nase) zu programmieren/korrigieren, was geradlinig hätte programmiert werden sollen.

Was flashback angeht: es kommt drauf an, wenn ihr z.B. häufig statt Tabellen zu aktualisieren, die Tabellen leert und neu aufbaut, was durchaus viele machen, dann ist flashback natürlich ein overkill, weil es alle Änderungen trackt.

Außerdem muss man sich - bzw. den Kunden - fragen: will er wirklich Historierung oder meint er einfach ein tägliches und über ARCHIVELOG bis auf die Sekunde wiederherstellbares Log für den Fall der Fälle? Meint er nicht eher eine backup-Strategie???

Schließlich: ist wirklich die Anforderung die, ALLE Tabellen zu historisieren - was ich durch die automatisch erstellten Trigger angenommen habe - dann sollte man doch dem flashback eine Chance geben. Schließlich entscheidet doch der benchmark und nicht die Ideologie. Für die Erstellung der Historie, wird flashback definitiv schneller sein, als die Trigger! Was die Auswertung angeht, müsste man schauen!

Das "plain" Oracle-DB Argument des Kunden verstehe ich auch nicht ganz. Für flashback bezahlt man nicht extra. Trigger gehören zu "plain" aber flashback nicht? Sollte man da nicht die Sichtweise ein Bisschen gerade rücken?
#zitieren
Gravatar Sascha 10.03.2010
um 22:15 Uhr
Hallo,

der Kunde wollte explizit eine Historisierung, die sofort alle Änderungen in einen historischen Bereich schiebt; diese Daten sollen zu jeder Zeit online verfügbar sein. Es ist keine Backup-Strategie, ansonsten hätten wir das Problem anders gelöst. Wir leeren die Tabellen nur über ein ETL bzw. Online-Tool, d.h., wenn wirklich explizit durch Anwender Daten gelöscht werden, was bislang noch nicht vorgekommen ist und zu 99% auch nicht vorkommen wird, da bei dem Anwendungsfall lediglich die Datenmenge ansteigt.
#zitieren