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!