1. Logical Unit of Work
Eine Logical Unit of Work is eine gruppe von Transaktionen, die gemeinsam, logisch gesehen, einen Block arbeit darstellen.
Ein Beispiel hierfür ist bei einer Banktransaktion: Person A überweist Person B 100€.
In der Datenbank passiert nun folgendes:
-
Person A: 100€ werden abgebucht
-
Person B: 100€ werden zum Kontostand hinzugefügt.
Dies ist eine logische Unit of work, da die beiden Transaktionen gemeinsam einen Arbeitsvorgang ausmachen
Das Problem: was würde passieren, wenn nun zwischen Transaktion 1 und 2 die Datenbank abstützt? Person A hätte nun 100€ weniger, Person B erhält nichts.
2. Transaktionen
Transaktionen sollten genau dieses Problem vermeiden. Beide diese Operationen werden nun in eine Transaktion verpackt. Erst wenn diese abgeschlossen ist, dann werden die Änderungen gespeichert. Im Falle eines Absturzes werden nur die fertigen Transaktionen wiederhergestellt. Alle nicht beendeten Transaktionen werden nicht gespeichert.
Dies führt zu einem konsistenten Zustand in der Datenbank.
"Entweder alles oder gar nichts"
3. Concurrency & Locking
Es gibt viele Gründe, warum concurrency auf einer Datenbank auftreten. Meist liegt es aber daran, dass viele Anfragen auf einmal kommen. Hierbei kann es zu mehreren Problemen kommen:
3.1. Verlorenes Update
Bei einem verlorenen Update, wie schon im Titel erkennbar, geht es darum, dass eine Änderung eines Datensatzes verloren geht.
Hierbei gibt es 2 Prozesse, die in unterschiedlicher Reihenfolge einen gewissen Datensatz updaten. Da dies allerdings parallel ausgeführt werden, kann es passieren, dass das Update des Prozesses 1 nicht in das Update des Prozesses 2 mit einfließt. Hierdurch geht das Update von Prozess 1 verloren
3.2. Schreib-Lese-Konflikt (Dirty Read / Write)
3.2.1. Dirty Read
Bei einem Dirty read, wird ein Datensatz ausgelesen, während ein anderer Prozess diesen verändert. Dadurch kann ein zwischenstatus ausgelesen werden, welcher allerdings nicht hätte gelesen werden sollen.
3.2.2. Dirty Write
Bei einem Dirty write wird ein Datensatz ausgelesen, während ein anderer Prozess diesen verändert, und diesen anschließend (nach dem Auslesen) zurücksetzt. Das Problem: Der alte noch nicht zurückgesetzte Datensatz wird nun wieder verändert, welches zu inconsistent Daten führen kann.
4. Locking
Wenn Prozess A eine Tabelle oder Datensatz benötigt, sperrt dieser diesen. Somit wird das falsche abändern durch andere Instanzen verhindert. Es gibt keinen Zugriff auf Objekte der DB, ohne ein Lock zu verwenden.
4.1. Locking types
Bei Locking gibt es zwei Ansätze:
-
Pessimistisch: Sperrt alle was gebraucht wird ("for update")
-
Optimistisch: Es wird schon nichts passieren, nur ein kurzer Vergleich auf Änderungen vor einem Update
4.3. Shared Lock
Bei einem shared lock werden alle X Lock Anfragen blockiert, S Lock Anfragen allerdings erlaubt
LOCKING |
X-Lock |
S-Lock |
Offen |
X-Lock |
Verboten |
Verboten |
Erlaubt |
S-Lock |
Verboten |
Erlaubt |
Erlaubt |
4.4. Deadlocks
Bei einem Deadlock sperren sich 2 Transaktionen gegenseitig. Hierbei möchten 2 verschiedene Transaktionen auf dieselben Resources zugreifen. Dafür wartet eine Transaktion standardmäßig darauf, dass eine Ressource frei wird. Wenn nun allerdings 2 oder mehr Transaktionen gegenseitig aufeinander warten, dann warten diese unendlich lange.
Dies nennt man einen Deadlock, da beide Transaktionen ewig aufeinander warten, und jeweils eine Resource haben, die sie nicht freigeben, bis die andere bereits belegte Resource frei ist.
4.5. Sperrtypen
Um Deadlocks zu verhindern, gibt es mehrere Sperrtypen in Oracle:
4.5.1. Two Phase Locking
Eine Transaktion sperrt gleich zu Beginn alle benötigten Ressourcen. Wenn dies allerdings nicht möglich ist, gibt diese alle Ressourcen wieder frei, und wartet ein bisschen, bis der Vorgang von vorne beginnt. Erst wenn alle benötigten Ressourcen gesperrt sind, darf die Transaktion ausgeführt werden.
Hierbei gibt es mehrere Probleme:
-
Alle Objekte sind am Start bekannt (Performance) (manchmal nicht möglich)
-
Bei großen Transaktionen werden über lange Zeit viele Datensätze gesperrt
-
Unabhängig keine festgelegte Reihenfolge der Transaktion
4.5.2. Transactions-Scheduling
Hierbei werden nur die Transaktionen parallel ausgeführt, die nicht auf dieselben Ressourcen zugreifen.
Probleme:
-
beschränkt parallele Durchführung (performance)
-
Nur unabhängige Transaktionen werden gleichzeitig ausgeführt
-
Pessimistisches Locking
-
Datenobjekte oft unbekannt → gesamte Tabelle wird gelockt.
4.6. Setzen von Locks
Locks können auch in Oracle händisch gesetzt werden. Dazu kann folgender SQL Code verwendet werden:
LOCK TABLE <TABLENAME> in row share mode;
LOCK TABLE <TABLENAME> in share mode;
LOCK TABLE <TABLENAME> in row exclusive mode;
LOCK TABLE <TABLENAME> in share row exclusive mode;
LOCK TABLE <TABLENAME> in exclusive mode;