Die Datenbank, das unbekannte Wesen Teil V

Die Transaktion

Im Teil IV hatten wir aufgehört mit 2 wichtigen Problemen bei Updates in der Datenbank. Diese gilt es jetzt zu erläutern.

Unsere Datenbank hatte immer einen Fehler beim Schreiben eines neuen Satzes. Der Fehler war „Datei voll“! Dies ist zugegebenermaßen, ein wenig vorkommender Fehler, doch der Einfachheit halber soll er „unser Fehler“ sein. In echt, können beliebig andere Fehler auf einer Datenbank vorkommen, die von Programmierfehlern oder Überlastungen der Datenbank reichen können. Denn kein großes Programm ist fehlerfrei!

Wir hatten es davon, dass die Datenbank einen Index schreiben wollte, aber die Datei voll war! Was passiert?

Um das zu erklären muss man den Begriff der Transaktion einführen. Eine Transaktion hat einen Beginn und ein Ende! Alles was innerhalb einer Transaktion verändert wird, wird zwischengespeichert und am Ende der Transaktion gibt es 2 Zustände richtig oder falsch! Im Falle richtig, wird der Zwischenspeicher gelöscht und im Falle falsch wird der alte Inhalt aller Veränderungen wieder an den richtigen Ort gestellt, als wäre nix passiert.

Manche Programme und Datenbanken haben einen Befehl wie „begin-transaction“ der eine Transaktion einleitet und 2 Befehle um sie abzuschließen „commit“ oder „rollback“. Im Falle

  • „commit“ ist alles OK und die Datenbank vergisst alles was zwischenzeitlich war!
  • „rollback“ wird der alte Zustand der Datenbank wieder hergestellt und ein Fehler gemeldet!

Auch der „Zwischenspeicher“ wo alle Veränderungen innerhalb einer Transaktion zwischengespeichert werden hat einen Namen, man nennt ihn „before-image“.

Wichtig zu wissen ist, dass Sie als Programmierer nur in der Lage sind zu entscheiden, wann eine Transaktion beginnt und wann sie aufhört! Stellen Sie sich vor, Sie haben eine Datenbank wo Sie Bestellungen von Produkten abwickeln. Ein neuer Benutzer schickt eine Bestellung. Dann müssen Sie ihn in die Benutzertabelle und seine Bestellung in die Bestelltabelle eintragen. Erst dann ist die Transaktion Bestellung abgeschlossen. Passiert ein Fehler, dann muss alles zurückgenommen werden.

Die Datenbank kann ja beim richtigen Anlegen des Benutzers nicht wissen, dass Sie auch noch die Bestelltabelle ändern wollen! Das wäre zu viel für die arme DB 🙂
Sie müssen der Datenbank sagen, so jetzt ok! Habe fertig! Commit!

Kommen wir zum 2. in Teil IV erwähnten Fall. Hier hatten wir einen Update auf eine Datenbank und dieser Update sollte einen weiteren Update auf einer 2. Datenbank erwirken. Sie haben also eigentlich 2 Transaktionen, denn eine normale Transaktion kann nur auf einer Datenbank definiert sein. Die 1. Transaktion wäre der Update auf Datenbank 1. Dort ist dann Transaktionsende (commit 1), dann schreiben Sie den Satz auf Datenbank 2 und ebenfalls commit – also commit 2!

Jetzt meldet die Datenbank 2 einen Datei-voll-Fehler! Was nun? Sie antworten mir rollback 2 auf die 2. Datenbank, was ist aber mit dem Satz auf der Datenbank 1? Dort hatten wir schon einen commit (commit 1)! Den Satz müssten wir eigentlich auch zurücknehmen, doch wegen commit1 weiß die Datenbank nicht mehr was da getrieben wurde. Sie brauchen also etwas anderes und auch das hat einen Namen: two-face-commit

Sie müssen der Datenbank sagen: „Achtung hier kommt ein two-face-commit! Auch wenn Du einen commit 1 bekommst, vergiss mich nicht, denn da kommen noch andere commits, ich sag Dir, dann wenn’s fertig ist“! Was muss die Datenbank damit anfangen?

Beim two-face-commit werden alle commits erst einmal gespeichert. Wenn dann alles fertig ist, erfolgt ein Rundgang auf alle in den Transaktionen angesprochenen Datenbanken. Jede Datenbank wird nach Fehler gefragt. Wenn nicht, dann geht am Ende des Rundgangs in geschützter Weise (Sie erinnern sich an die Serialisierung!) ein Rundgang, wo jede Transaktion auf allen Datenbanken einen endgültigen commit erhält. Schwierig nicht!

Die Frage ist, kann all das eine Datenbank alleine? Ohne dass ich ihr andauernd sagen muss, wo’s lang geht? Antwort: NEIN!

Gibt es eine andere Möglichkeit?

Sie könnten sich überlegen, dass Sie den Zugriff auf eine Tabelle sperren. Dazu gibt es auf vielen Datenbanken (auch MySQL) eine Operation! Sie sperren also die Datenbanktabellen und machen die Updates, dann geben Sie diese wieder frei. Nur was ist mit den before-images? Wer speichert die? Antwort: SIE!

Wenn aber eine Datenbanktabelle gesperrt ist, dann kann meist auch kein anderer lesen, es sei denn, die Datenbank unterstützt den Dirty Read (aus Teil IV)!
Was aber wenn eine Sperre bestehen bleibt, weil der Server einen Aussetzer hat?

Außerdem überlegen Sie sich mal, was das für Ihre Webseite bedeutet? Alle in den Transaktionen angesprochenen Veränderungen müssen auf einer Seite beim Absenden eines Formulars passieren. (Erinnern Sie sich an die Verbindungslosigkeit)! Wenn Sie über mehrere Seiten diese Daten lesen, dann könnte sich der Benutzer einer anderen Seite zugewendet haben. Und Sie sitzen auf Ihren gesperrten Tabellen rum!

Sie sehen, all diese Überlegungen haben auch Auswirkungen auf Ihre Programmierung der Website!

Fehlermeldungen

War es bei den Transaktionen schon nicht leicht zu verstehen, was in der Datenbank abgehen muss, ist es bei gesperrten Tabellen noch wichtiger, jederzeit zu wissen, wie der Zustand der Datenbank ist. Denn Sie programmieren auf dem Server ja die Datenbankaufrufe.
Umso verwunderlicher ist es, wenn man sich einige Datenbank steuernden Programme anschaut, wo einfach ein insert-Befehl abgesendet wird und eine etwaige Fehlermeldung der Datenbank überhaupt ganz ignoriert wird. Es gibt hunderte – wenn nicht tausende – Programme, die bei SQL-Befehlen keine Fehlerrückmeldung berücksichtigen.

Gut kann ich mich an das schon erwähnte Programm erinnern, wo in den Routinen insert und update nur geprüft wurde, ob der Befehl auf die richtige Datenbank geht. Ein Fehlerrückgabe-Code der Datenbank wird nie geprüft. Prompt ging natürlich der Update-Befehl auf die 2. Datenbank schief, doch das Programm meldete nichts.

Ok, ich sehe ein, wenn ich einen Befehl wie select (lese Daten) getestet habe, dann bin ich mir sicher, dass die Datenbank genau diese Felder lesen wird. Warum soll ich dann Aufwand betreiben, um eine Fehlerroutine zu versorgen? „Hat doch immer geklappt“! Wenn Sie jetzt aber ein Feld in der Datenbank in eine andere Tabelle verlegt haben, und Sie passen nicht Ihr Coding an, bekommen Sie hier keinen Satz geliefert, sondern eine Fehlermeldung, die Sie ja ignorieren. D.h. Sie erhalten in Ihren Felder leere Inhalte. Das muss Sie ggf. nicht unbedingt stören, doch wenn Sie im Falle gefüllter Rückgabefelder anders programmiert haben, als im Falle leerer Felder, ist da ggf. doch ein Kümmernis.

Deshalb sollten Sie nie vergessen den Rückgabe Code der Datenbank zu prüfen.

Situation in MySQL

Wie sind alle diese Forderungen und Problematiken in MySQL verwirklicht? Da haben wir das Problem! Je nach Vertrag mit Ihrem Hoster dürfen Sie nur bestimmte Arten von Tabellen in der Datenbank MySQL definieren, oder Sie müssen sich einen eigenen Server mieten.

Welche Arten von Tabellen werden hier angesprochen? MySQL hat 2 Arten von Tabellen eine MyIsam und InnoDB.

MyIsam ermöglicht es Ihnen Tabellen zu definieren und diese zu betreiben. Sie haben eine Sperrmöglichkeit aber keine Transaktionen!
InnoDB ermöglichst es Ihnen so etwas wie Transaktionen anzulegen und zu betreiben. Dazu gibt es extra Datenbankaufrufe wie begin_transaction, commit und rollback!. Sie haben aber – wenigstens habe ich das noch nicht gefunden – keinen two-face-commit.

Sicherlich, es steht Ihnen frei eine Transaktionsunterstützung zu bauen und diese mit Sperren und Entsperren von Tabellen zu realisieren. Doch dürfte dieses Vorhaben ziemlich langwierig werden. Erkundigen Sie sich also beim Hoster, ob Sie InnoDB anwenden dürfen.

Die meisten Datenbankanwendungen, die ich im Web kennengelernt habe, nehmen MyIsam und vertrauen darauf, dass alles gut geht. Es wird munter – wie man am Beispiel 2 des Teils IV sieht – drauf los programmiert und dafür auch noch ein heiden Geld eingenommen. Bei Nachfragen, bekommt man zur Antwort: „Das unterstützen wir nicht, hatten bisher keine Fehler!“

Und jetzt sehen Sie, dass es sogar für den Datenbestand gefährlich sein kann, wenn man mit mehreren Datenbanken arbeitet. Was unsere Entscheidungswaage des Teils IV mal schlichtweg aus dem Gleichgewicht bringt und enorm nach 1 Datenbank-viele Tabellen ausschlagen lässt.

Welche Forderungen für den Betrieb der Datenbank und vor allem der Datenbankprogrammierung hier auftreten, werde ich im nächsten Artikel zeigen.

Bis dorthin kann ich nur wieder auffordern, wenn es Verständnisschwierigkeiten gibt, dann schreiben Sie einen Kommentar.

Bernd Klüppelberg

Hier noch alle Links auf die Artitkelserie (soweit sie veröffentlicht ist):
Die Datenbank, das unbekannte Wesen Teil I
Die Datenbank, das unbekannte Wesen Teil II
Die Datenbank, das unbekannte Wesen Teil III
Die Datenbank, das unbekannte Wesen Teil IV
Die Datenbank, das unbekannte Wesen Teil VI

Bisher gibt es keinen Kommentar. Schreiben Sie einen Kommentar!

Schreibe einen Kommentar