Datenbanktransaktionen, ACID, CAP-Theorem und BASE – IT-Berufe-Podcast #187
Um Datenbanktransaktionen, die ACID-Prinzipien und Alternativen
dazu geht es in der einhundertsiebenundachzigsten Episode des
IT-Berufe-Podcasts. Inhalt Datenbanktransaktionen sollten
jedem/jeder ITler:in etwas sagen,
1 Stunde 17 Minuten
Podcast
Podcaster
Beschreibung
vor 1 Jahr
Um Datenbanktransaktionen, die ACID-Prinzipien und Alternativen
dazu geht es in der einhundertsiebenundachzigsten Episode des
IT-Berufe-Podcasts.
Inhalt
Datenbanktransaktionen sollten jedem/jeder ITler:in etwas sagen,
da wir fast täglich mit datenbankgestützten Anwendungen arbeiten,
egal, ob wir selbst diese Anwendungen programmieren oder „nur“
Abfragen gegen eine Datenbank durchführen.
Was ist eine Datenbanktransaktion?
Eine Transaktion ist eine Menge aus mehreren
zusammenhängenden Datenbankoperationen, die gemeinsam als eine
Einheit durchgeführt werden müssen.
Beispiele für Datenbanktransaktionen:
Banküberweisung von 100 EUR von Konto DE123 auf Konto DE432
UPDATE konto SET kontostand = kontostand - 100 WHERE iban
= 'DE123';
UPDATE konto SET kontostand = kontostand + 100 WHERE iban
= 'DE432';
Neuen Tag katze zu einem Blog-Post mit ID 123 hinzufügen
INSERT INTO tag (id, name) VALUES (1, 'katze');
INSERT INTO tag_post (post_id, tag_id) VALUES (123, 1);
Neue Bestellung für einen Kunden mit ID 324 erfassen für
Artikel 253
INSERT INTO bestellung (id, datum, kunde_id) VALUES (123,
'2024-04-10', 324);
INSERT INTO bestellposition (bestellung_id, artikel_id,
menge, preis) VALUES (123, 253, 1, 123.92);
Neuen Tarifsatz einer Versicherung anlegen und bisherigen
beenden
UPDATE tarif SET gueltig_bis='2024-04-10' WHERE id=122;
INSERT INTO tarif (id, gueltig_ab, beitrag) VALUES (123,
'2024-04-10', 143.23);
Begriffsabgrenzung
Eine Datenbanktransaktion ist nicht zu verwechseln mit einer
Transaktion im Geschäftsbetrieb, z.B. einer Überweisung bei einer
Bank, dem Kauf eines Autos oder der Buchung eines Fluges.
Die ACID-Prinzipien
Datenbanktransaktion müssen/sollen bestimmten Kriterien genügen,
die als ACID-Prinzipien bekannt sind.
Atomarität/Atomicity: Alle
Datenbankoperationen werden entweder vollständig gemeinsam
durchgeführt oder gar nicht. Es kann nicht sein, dass nur einige
Operationen durchgeführt werden und andere nicht. Dazu werden die
Datenbankoperationen in eine Transaktion „eingeklammert“.
Beispiel: Bei der Banküberweisung darf nicht nur Geld
abgebucht oder gutgeschrieben werden, sondern beide Buchungen
müssen gemeinsam durchgeführt werden.
Konsistenz/Consistency: Wenn die Datenbank
vor der Transaktion in einem konsistenten Zustand war, dann muss
sie es auch nach der Transaktion sein.
Beispiel: Bei der Banküberweisung bleibt der Gesamtbetrag
an Geld gleich. Es entsteht kein Geld aus dem Nichts und es
geht auch kein Geld verloren.
Isolation/Isolation: Mehrere Transaktionen
dürfen sich nicht gegenseitig beeinflussen. Hierzu folgen weiter
unten verschiedene Maßnahmen zur Umsetzung.
Beispiel: Bei zwei parallelen Banküberweisungen vom
gleichen Konto müssen beide Beträge nacheinander abgebucht
werden und nicht nur der der zuletzt durchgeführten
Transaktion.
Dauerhaftigkeit/Durability: Die Daten müssen
nach Abschluss der Transaktion persistent gespeichert sein und
z.B. auch einen Systemausfall überstehen. Das wird durch
sogenannte Transaktionslogs sichergestellt.
Beispiel: Wenn nach dem Abschluss einer Transaktion der
Datenbankprozess abstürzt, müssen auch nach dem Neustart der
Datenbank die aktualisierten Daten vorhanden sein.
Maßnahmen zur Wahrung der Isolation von Transaktionen
Wenn Transaktionen nicht isoliert voneinander ablaufen, können
verschiedene Probleme in der Datenbank auftreten.
Dirty Read: Veränderte Daten einer noch
offenen Transaktion werden von einer anderen Transaktion
gelesen und weisen somit einen „dreckigen“ Zustand auf, weil er
noch nicht final ist.
Beispiel: Bei einem Ticketkauf geht die zweite Buchung
schon vom veränderten Bestand der ersten Transaktion aus.
Lost Updates: Wenn zwei Transaktionen
gleichzeitig denselben Datensatz verändern, „gewinnt“ die
Änderung der zuletzt durchgeführten Transaktion und die der
ersten ist verloren.
Beispiel: Bei zwei Banküberweisungen wird der Kontostand
auf den Ursprungsstand abzgl. der zweiten Überweisung
gesetzt, aber ohne die erste Überweisung abzuziehen.
Non-Repeatable Read: Wiederholte Lesevorgänge
innerhalb einer Transaktion liefern unterschiedliche
Ergebnisse.
Beispiel: Bei einer Flugbuchung wird geprüft, ob noch
ausreichend Plätze frei sind, aber durch eine parallele
Buchung wird bei der zweiten Abfrage ein unterschiedliches
Ergebnis geliefert.
Phantom Read: Während eine Transaktion
Datensätze nach einem bestimmten Kriterium liest, werden
weitere Datensätze zum gleichen Kriterium
hinzugefügt/gelöscht/verändert.
Beispiel: Während der Durchschnittsberechnung von
Gehältern von Mitarbeiter:innen wird ein neuer Mitarbeiter
hinzugefügt, der beim Summieren des Gehalts noch nicht
berücksichtigt wird, aber beim Zählen der Datensätze dann
schon.
Die Datenbank kann verschiedene
Transaktionsisolationsebenen implementieren, um
den obigen Problemen entgegenzuwirken. Grundsätzlich werden dabei
Sperren verwendet, um die gleichzeitige
Verarbeitung der Daten einzuschränken. Es kann dabei eine
Lesesperre und/oder eine
Schreibsperre gesetzt werden, wodurch das
gleichzeitige Lesen bzw. Schreiben eingeschränkt wird.
Read Uncommitted: Es werden keine Sperren
verwenden. Quasi kein Schutz vor obigen Problemen. Vergleichbar
mit NO ACTION bei referenzieller Integrität.
Read Committed: Für die gesamte Transaktion
werden Schreibsperren auf alle beteiligten Objekte gesetzt, die
verändert werden sollen. Lesesperren werden aber nur kurzzeitig
gesetzt. Es können Non-Repeatable Read und Phantom Read
auftreten.
Repeatable Read: Es werden für die gesamte
Transaktion Lese- und Schreibsperren auf alle beteiligten
Objekte gesetzt. Nur Phantom Reads können noch auftreten (weil
dabei zwei lesende Operationen mit unterschiedlichen Kriterien
durchgeführt werden).
Serializable: Die Datenbank verhält sich so,
als würden die Transaktionen komplett separiert nacheinander
(„seriell“) durchgeführt. Dabei kann keines der obigen Probleme
mehr auftreten, aber Transaktionen müssen ggfs. abgebrochen
werden. Starten z.B. zwei Flugbuchungen für zwei Sitzplätze
parallel auf dem Sitzplatzbestand von 2, wird die erste
Transaktion den Bestand auf 0 reduzieren und die zweite
Transaktion (die „gewartet“ hat) muss abbrechen, weil die
Sitzplätze nun nicht mehr ausreichen.
Umsetzung in SQL
Mit der Transaction Control Language (TCL) gibt
es eine eigene Familie an SQL-Befehlen, die sich nur um die
Transaktionssteuerung kümmert. Hiermit können
Datenbankoperationen zu einer Transaktion zusammengefasst werden.
BEGIN TRANSACTION: Startet eine Datenbanktransaktion.
COMMIT: Beendet eine Datenbanktransaktion und schreibt die
Änderungen fest.
ROLLBACK: Rollt eine Datenbanktransaktion zurück und verwirft
alle Änderungen.
In vielen Datenbanken muss man nicht explizit Transaktionen
starten und beenden. Sie verwenden ein sogenanntes
Auto-Commit. Dabei wird jedes Statement in einer
eigenen Transaktion durchgeführt.
Umsetzung in ORMs
Brauche ich als Softwareentwickler:in überhaupt Wissen über
Datenbanktransaktionen? In modernen Entwicklungsprojekten werden
doch sowieso objektrelationale Mapper (ORM) verwendet. Doch auch
diese ORMs können natürlich nicht zaubern, sondern verwenden
unter der Haube die normalen Datenbankoperationen. Daher ist auch
bei Verwendung eines ORMs wichtig zu wissen, welche Operationen
in einer gemeinsamen Transaktion durchgeführt werden müssen.
Dafür bieten viele ORMs entsprechende Befehle an. Jakarta EE hat
sogar einen eigenen Standard dafür: Jakarta Transactions (JTA).
Dort wird z.B. Annotation @Transactional verwendet. Diese wird an
eine Java-Methode geschrieben, die dann automatisch innerhalb
einer Datenbanktransaktion ausgeführt wird. Im Fall einer
aufgetretenen Exception wird dabei dann automatisch ein Rollback
durchgeführt.
CAP und BASE
Transaktionen nach den ACID-Prinzipien sind ein wichtiger
Bestandteil vieler Datenbanksysteme. Sobald die Datenbank jedoch
auf mehrere Knoten verteilt wird, können Transaktionen zu einem
Problem werden. Das sogenannte CAP-Theorem
besagt, dass es in einem verteilten System nicht möglich ist,
alle drei Eigenschaften Konsistenz, Verfügbarkeit und
Ausfalltoleranz gleichzeitig zu garantieren.
Konsistenz (Consistency): Die Konsistenz
meint in diesem Kontext den einheitlichen Datenstand über alle
Datenbankknoten hinweg (und nicht die Konsistenz vor/nach einer
Transaktion). Egal, welcher Knoten abgefragt wird, es werden
immer die gleichen Daten zurückgegeben.
Verfügbarkeit (Availability): Die Datenbank
antwortet in akzeptabler Zeit auf alle Anfragen. Dabei kann es
jedoch sein, dass nicht immer die aktuellsten Daten geliefert
werden.
Partitionstoleranz (Partition tolerance):
Die Datenbank arbeitet auch weiter, wenn einzelne Knoten
ausfallen.
Angenommen, die verteilte Datenbank soll zu jedem Zeitpunkt in
einem konsistenten Zustand sein (also alle Informationen auf
allen Knoten sollen identisch sein), dann führt ein Ausfall eines
Knoten automatisch dazu, dass eine Transaktion fehlschlagen muss,
da der ausgefallene Knoten nicht sofort aktualisiert werden kann.
Die Konsistenz wäre dann zwar gewährleistet, aber die
Partitionstoleranz nicht.
Da heutzutage viele Anwendungen tatsächlich mit verteilten
Datenbanken arbeiten, wurde mit BASE ein
Gegenentwurf zu ACID geschaffen. Das Wort ist
etwas konstruiert, um das Gegenstück zu ACID zu bilden. Aus der
Chemie kennen wir den Unterschied zwischen Säure („acid“) und
Lauge („base“). Im Kern stellt ACID die Konsistenz eines Systems
sicher, während BASE die Verfügbarkeit in den Vordergrund stellt.
Basically Available: Die
Datenbank ist grundsätzlich für alle Benutzer jederzeit
erreichbar (hohe Verfügbarkeit).
Soft state: Daten können sich im Laufe der
Zeit verändern und temporäre („weiche“) Zustände annehmen, wenn
mehrere Änderungen parallel durchgeführt werden.
Eventual consistency: Irgendwann einmal werden
die Daten in der Datenbank einen konsistenten Zustand
erreichen. Bis dahin können Anfragen unterschiedliche
Ergebnisse produzieren.
Vorsicht „false friend“: „eventually“ heißt auf Deutsch
„schlussendlich“ und nicht „eventuell“. Es wird also immer
Konsistenz erreicht, nur eben nicht unmittelbar sofort.
Literaturempfehlungen
*
In Kapitel 13 gibt es eine gute und kurze Einführung in das Thema
Datenbanken inkl. Transaktionen. Ich habe das Kapitel auch schon
im Buchclub besprochen: Buchclub: Handbuch für Fachinformatiker
(Teil 11: Datenbanken)
Links
Permalink zu dieser Podcast-Episode
RSS-Feed des Podcasts
ACID – Wikipedia
Isolation (Datenbank) – Wikipedia
START TRANSACTION, COMMIT, and ROLLBACK Statements
autocommit, Commit, and Rollback
Jakarta Transactions 2.0
Annotation @Transactional in Jakarta EE
CAP-Theorem – Wikipedia
Unterschied zwischen ACID- und BASE-Datenbanken
Weitere Episoden
5 Minuten
vor 3 Wochen
11 Minuten
vor 4 Monaten
8 Minuten
vor 4 Monaten
8 Minuten
vor 4 Monaten
10 Minuten
vor 5 Monaten
In Podcasts werben
Kommentare (0)