Was ist eigentlich... ROLLBACK und COMMIT?

In diesem Artikel beschäftigen wir uns mit SQL Transaktionen. Was ist eine Transaktion? Wofür braucht man das überhaupt? Wie wird sie verwendet? Und natürlich: Was ist eigentlich ROLLBACK und COMMIT?

 

Transaktion

Als SQL Einsteiger befasst man sich normalerweise zunächst mit SELECT-Statements. Wir lernen, Informationen aus Datenbanken zu holen. Das brauchen wir meist zuerst. In einem der nächsten Lernschritte erfahren wir dann, wie wir Informationen, die sich in der Datenbank befinden, verändern können.

Das Verändern von Informationen in der Datenbank gehört zum Tagesgeschäft – in einer Kundendatenbank beispielsweise verändert sich ständig irgendetwas: Jemand ändert den Namen, die Adresse oder Telefonnummer; der Kundenstatus ändert sich oder die offenen Beträge.

Dass wir die Daten in der Datenbank ändern können, ist ganz selbstverständlich – es bringt aber auch Gefahren mit sich. Was, wenn zwei Sachbearbeiter/innen gerade gleichzeitig die gleichen Daten verändern wollen? Was, wenn jemand gerade Daten verändert, während jemand anderer sie gleichzeitig abfragen möchte? Haben wir dann schon die aktuellen Daten oder noch die alten? Was, wenn das System abstürzt, während gerade jemand eine Überweisung tätigen möchte? Steht dann beim Kunden, das Geld wurde schon abgebucht und bei der Bank, es sei noch ausständig?

Damit uns so etwas nicht passieren kann, brauchen wir die Transaktion. Sie sorgt dafür, dass eine Transaktion, wie beispielsweise das Überweisen eines Betrages, entweder ganz oder gar nicht ausgeführt wird. Weiters stellt sie sicher, dass auf Daten, die gerade bearbeitet werden, nicht von anderer Seite her zugegriffen werden kann.

 

ROLLBACK und COMMIT am Beispiel UPDATE

Sehen wir uns das am Beispiel UPDATE an. Wir wollen einen Namen in einer Datenbank ändern. Unsere Kundendatenbank sieht derzeit so aus:


Minnie wird das Kundenkonto übernehmen, und somit haben wir nicht viel zu tun, wir müssen nur den Vornamen von Mickey auf Minnie umändern. Dafür brauchen wir nur ein einfaches UPDATE:


Gleich darauf werfen wir noch einen Blick in unsere Tabelle und stellen fest, O Graus! uns ist ein Fehler unterlaufen. Wir haben damit alle Vornamen in „Minnie“ umgeändert:


Und das war es dann. Wir haben keine Möglichkeit mehr, das rückgängig zu machen. Wenn wir jetzt nicht fünf, sondern fünftausend Kunden haben (oder mehr), können wir nur noch hoffen, dass es irgendwo ein Backup von unserer Datenbank gibt – aber auch das wäre katastrophal, denn dann würden wir nicht nur unseren Fehler zurücksetzen, sondern alle Änderungen, die seither vorgenommen wurden.

Die Transaktion kann uns unter anderem vor diesem Horrorszenario schützen. Solange wir die Tranksaktion nicht mit einem COMMIT abgeschlossen haben, ist an der Datenbank noch nichts passiert, und wir können auch wieder zurücksetzen.

Wenn unser einfaches UPDATE innerhalb einer Transaktion durchgeführt wird, sieht das so aus:

Oh nein!, wir haben den gleichen Fehler gemacht, wie zuvor… aber jetzt haben wir zwei Vorteile: Einerseits bekommen wir beim Ausführen einen Hinweis, dass das nicht ganz stimmen kann:


Wenn wir nur einen Vornamen ändern wollten, wie kann es dann fünf Zeilen betreffen? Hoffentlich bemerken wir hier den Fehler.

Andererseits haben wir jetzt dank der Transaktion die Möglichkeit, alles noch einmal rückgängig zu machen: dafür gibt es das ROLLBACK.


Damit ist dann nocht nichts passiert, nichts in der Datenbank verändert worden.

Erst, wenn wir ein COMMIT machen, greift die Veränderung (und hoffentlich korrigieren wir vorher unseren Fehler).



Blockieren von Daten in Verwendung

Weiters werden Daten, auch ganze Tabellen, die gerade in Verwendung sind, blockiert. So einen Fall haben wir zum Beispiel, wenn wir gerade Zugtickets oder Kinoplätze reservieren wollen. Wenn jemand anderer gerade die Plätze ausgewählt hat, stehen sie uns nicht zur Verfügung – und zwar so lange nicht, bis derjenige die Plätze entweder gekauft hat (erst dann werden sie uns als bereits besetzt angezeigt) oder der Verkauf abgebrochen wurde und wir uns die letzte Reihe unter den Nagel reißen können.


Das passiert auch bei unserem simplen Beispiel – solange unser UPDATE nicht mit dem COMMIT abgeschlossen wurde, hat auch sonst niemand Zugriff auf die Daten.


Andere stecken solange in der Warteschleife (selbst, wenn sie nur eine Tabellenabfrage machen und nichts verändern wollen):



Savepoints: Transaktionen verschachteln

Transaktionen können auch miteinander verschachtelt werden, oder mit anderen Worten, wir können innerhalb einer Transaktion Savepunkte erstellen, zu denen zurückgesetzt werden kann. In diesem Fall vergeben wir auch Namen für die Transaktionen, um eben zu einem bestimmten Punkt zurücksetzen zu können.

In unserem einfachen Beispiel könnte das etwa so aussehen:


Die verschachtelten Transaktionen beginnen wir mit SAVE TRAN statt mit BEGIN TRAN um einen Savepoint zu erstellen.

Versuchen wir, eine verschachtelte Transaktion zurückzusetzen, wenn wir versehentlich mit BEGIN TRAN versucht haben, eine Verschachtelung zu erstellen, bekommen wir die Fehlermeldung, dass keine Transaktion dieses Namens gefunden wurde und die Transaktion wird ausgeführt!

 


Transaktionsnamen und Transaktionslog

Damit wir bei mehreren Verschachtelungen feststellen können, welche wir denn jetzt zurücksetzen (oder ausführen) möchten, brauchen unsere Transaktionen Namen. Auch wenn wir mit dem Transaktionslog arbeiten, ist es hilfreich, wenn unsere Transaktionen wiedererkennbare Namen haben, um sie leichter einordnen zu können:


Das Transaction-Log können wir zum Beispiel so aufrufen:

Der erste Wert in der Klammer steht dabei für starting log sequence number (LSN), der zweite Wert steht für die ending LSN. NULL, NULL bedeutet einfach alles.

Auch nach bestimmten Transaktionen können wir suchen, wenn wir dem SELECT noch ein WHERE mitgeben:



Viel Spaß beim Ausprobieren, und vielleicht sehen wir uns ja einmal in einem unserer Kurse zum Thema SQL!










Kommentare sind geschlossen