Skip to content

7. Verwaltung des gleichzeitigen Zugriffs auf Daten

Bisher haben wir Tabellen verwendet, deren einzige Nutzer wir selbst waren. In der Praxis werden Daten auf einem Mehrbenutzer-Rechner meist von verschiedenen Benutzern gemeinsam genutzt. Dabei stellt sich die Frage: Wer darf welche Tabelle nutzen und in welcher Form (Abfrage, Einfügen, Löschen, Hinzufügen, ...)?

7.1. Anlegen von Firebird-Benutzern

Bei der Arbeit mit IB-Expert haben wir uns als Benutzer SYSDBA angemeldet. Diese Information findet sich in den Eigenschaften der offenen Verbindung zu SGBD:

Rechts ist zu sehen, dass der angemeldete Benutzer [SYSDBA] ist. Was man nicht sieht, ist sein Passwort [masterkey]. [SYSDBA] ist ein spezieller Firebird-Benutzer: Er verfügt über alle Rechte an allen Objekten, die von SGBD verwaltet werden. Mit IBExpert lassen sich neue Benutzer erstellen, entweder mit der Option [Tools / User Manager] oder über das folgende Symbol:

Image

Es erscheint das Fenster zur Benutzerverwaltung:

Image

Über die Schaltfläche [Add] können neue Benutzer angelegt werden:

Image

Lassen Sie uns also die folgenden Benutzer anlegen:

Name
Passwort
ADMIN1
admin1
ADMIN2
admin2
SELECT1
select1
SELECT2
select2
UPDATE1
update1
UPDATE2
update2

7.2. Zugriffsrechte für Benutzer vergeben

Eine Datenbank gehört demjenigen, der sie angelegt hat. Die Datenbanken, die wir bisher angelegt haben, gehörten dem Benutzer [SYSDBA]. Um das Konzept der Rechte zu veranschaulichen, legen wir (Database / Create Database) eine neue Datenbank unter der Kennung [ADMIN1, admin1] an:

Image

und speichern wir sie unter dem Alias DBACCES (ADMIN1). Durch die Verwendung von Aliasen können Verbindungen zu derselben Datenbank mit unterschiedlichen Bezeichnern geöffnet werden, wodurch sie im Datenbank-Explorer von IBExpert besser zu erkennen sind:

Erstellen wir nun die folgenden beiden Tabellen TA und TB:

Tabelle TA

Tabelle TB

Diese Tabellen stehen in keiner Verbindung zueinander.

Lassen Sie uns mit IB-Expert eine zweite Verbindung zur Datenbank [DBACCES] herstellen, diesmal unter dem Namen [ADMIN2 / admin2]. Dazu verwenden wir die Option [Database / Register Database]:

Wechseln wir zu DBACCES (ADMIN2) und öffnen wir einen Editor SQL (Umschalt + F12):

Wir werden verschiedene Verbindungen zur selben Datenbank [DBACCES] nutzen. Für jede dieser Verbindungen steht uns ein Editor SQL zur Verfügung. In [1] gibt der Editor SQL den Alias der verbundenen Datenbank an. Nutzen Sie diesen Hinweis, um festzustellen, in welchem Editor SQL Sie sich befinden. Dies ist wichtig, da wir Verbindungen erstellen werden, die nicht dieselben Zugriffsrechte auf die Objekte der Datenbank haben.

Rufen wir den Inhalt der Tabelle TA ab:

Image

Wir erhalten folgende Fehlermeldung:

Image

Was bedeutet das? Die Datenbank [DBACCESS] wurde vom Benutzer [ADMIN1] angelegt und ist somit sein Eigentum. Nur er hat Zugriff auf die verschiedenen Objekte dieser Datenbank. Er kann anderen Benutzern mit dem Befehl SQL GRANT Zugriffsrechte gewähren. Dieser Befehl hat verschiedene Syntaxvarianten. Eine davon lautet wie folgt:

syntaxe
GRANT Berechtigung1, Berechtigung2, ...| ALL PRIVILEGES
ON table/vue
TO Benutzer1, Benutzer2, ...| PUBLIC
[ WITH GRANT OPTION ]
action
gewährt Zugriffsrechte privilègei oder alle Rechte (ALL PRIVILEGES) auf table oder vue für die Benutzer utilisateuri oder für alle Benutzer (PUBLIC). Die Klausel WITH GRANT OPTION ermöglicht es Benutzern, denen die Berechtigungen erteilt wurden, diese wiederum an andere Benutzer weiterzugeben.

Zu den Berechtigungen privilègei, die erteilt werden können, gehören die folgenden:

DELETE
Recht zur Verwendung des Befehls DELETE für die Tabelle oder Ansicht.
INSERT
Berechtigung zur Verwendung des Befehls INSERT für die Tabelle oder Ansicht
SELECT
Berechtigung zur Verwendung des Befehls SELECT für die Tabelle oder Ansicht
UPDATE
Berechtigung zur Verwendung des Befehls UPDATE für die Tabelle oder Ansicht. Dieses Recht kann durch folgende Syntax auf bestimmte Spalten beschränkt werden: GRANT update (col1, col2, ...) ON Tabelle/Ansicht TO Benutzer1, Benutzer2, ...| PUBLIC [ WITH GRANT OPTION ]

Wir erteilen dem Benutzer [ADMIN2] das Recht SELECT für die Tabelle TA. Nur der Eigentümer der Tabelle kann dieses Recht vergeben, c.a.d. Hier ist das [ADMIN1]. Wechseln wir zur Verbindung DBACCES (ADMIN1) und öffnen wir einen neuen Editor SQL (Umschalt+F12):

Image

Anschließend wechseln wir zwischen den beiden Editoren SQL hin und her. Um den Überblick zu behalten, können wir die Option [Windows] im Menü verwenden:

Image

Oben sind die beiden Editoren SQL zu sehen, die jeweils einem bestimmten Benutzer zugeordnet sind. Kehren wir zum Editor SQL (ADMIN1) zurück und geben wir den folgenden Befehl ein:

Image

Anschließend bestätigen wir ihn mit einem COMMIT:

Image

Anschließend wechseln wir in den Editor des Benutzers ADMIN2, um den fehlgeschlagenen Befehl SELECT erneut auszuführen:

Image

Wir erhalten folgende Fehlermeldung:

Image

Der Benutzer [ADMIN2] hat nach wie vor keine Berechtigung, die Tabelle [TA] einzusehen. Tatsächlich scheinen die Berechtigungen eines Benutzers zum Zeitpunkt der Anmeldung geladen zu werden. [ADMIN2] hätte dann immer noch dieselben Berechtigungen wie zu Beginn seiner Anmeldung, d. h. keine. Überprüfen wir das. Melden wir den Benutzer [ADMIN2] ab:

  • Wählen Sie seine Verbindung aus
  • die Abmeldung anfordern, indem man mit der rechten Maustaste auf die Verbindung klickt und die Option „[Deconnect from database]“ wählt oder (Umschalt + Strg + D)

Image

Falls ein Fenster nach einem [COMMIT] fragt, geben Sie [COMMIT] ein. Melden Sie anschließend den Benutzer [ADMIN2] erneut an, indem Sie die oben genannte Option [Reconnect] wählen. Anschließend kehren wir zum Editor SQL (ADMIN2) zurück und führen die fehlgeschlagene Anfrage SELECT erneut aus:

Image

Wir erhalten dann das folgende Ergebnis:

Image

Diesmal kann ADMIN2 dank der Berechtigung SELECT, die ihm sein Eigentümer ADMIN1 erteilt hat, auf die Tabelle TA zugreifen. Normalerweise ist dies die einzige Berechtigung, über die es verfügt. Überprüfen wir dies. Wieder im Editor SQL (ADMIN2):

Der Bildschirm auf der rechten Seite zeigt, dass ADMIN2 nicht über die Berechtigung DELETE für die Tabelle TA verfügt.

Kehren wir zum Editor von SQL (ADMIN1) zurück, um dem Benutzer ADMIN2 weitere Rechte zu erteilen. Wir geben nacheinander die folgenden beiden Befehle ein:

  • Der erste Befehl gewährt dem Benutzer ADMIN2 alle Zugriffsrechte auf die Tabelle [TA] sowie zusätzlich die Möglichkeit, selbst Rechte zu vergeben (WITH, GRANT, OPTION)
  • Der zweite Befehl bestätigt den vorherigen

Anschließend erneuern wir wie zuvor die Verbindung des Benutzers [ADMIN2] (Abmelden / Erneut anmelden) und geben dann im Editor SQL (ADMIN2) die folgenden Befehle ein:

ADMIN2 hat alle Zeilen der Tabelle TA gelöscht. Machen wir diese Löschung mit einem ROLLBACK rückgängig:

Überprüfen wir, ob ADMIN2 wiederum Berechtigungen für die Tabelle TA vergeben kann.

Erstellen wir nun eine Verbindung zur Datenbank [DBACCES] (Datenbank / Datenbank registrieren) unter dem Namen [SELECT1 / select1], einem der zuvor angelegten Benutzer, und doppelklicken wir anschließend auf den so erstellten Link in [Database Explorer]:

Wechseln wir zu dieser neuen Verbindung und öffnen wir einen neuen Editor SQL (Umschalt + F12), um dort die folgenden Befehle einzugeben:

Der Benutzer SELECT1 verfügt tatsächlich über die Berechtigung SELECT für die Tabelle TA. Hat er die Möglichkeit, diese Berechtigung an den Benutzer SELECT2 zu übertragen?

 

Der Vorgang ist fehlgeschlagen, da der Benutzer SELECT1 nicht die Berechtigung erhalten hat, die Berechtigung SELECT weiterzugeben, die er vom Benutzer ADMIN2 erhalten hat. Dazu hätte derBenutzer ADMIN2 die Klausel WITH GRANT OPTION in seinem Befehl SQL GRANT. Die Regeln für die Weitergabe sind einfach:

  • Ein Benutzer darf nur die Rechte weitergeben, die er erhalten hat, und nicht mehr
  • er darf sie nur weitergeben, wenn er sie mit dem Privileg [WITH GRANT OPTION] erhalten hat

Ein gewährtes Recht kann mit dem Befehl REVOKE widerrufen werden:

syntaxe
REVOKE Berechtigung1, Berechtigung2, ...| ALL PRIVILEGES
ON table/vue
FROM Benutzer1, Benutzer2, ...| PUBLIC
action
entfernt die Zugriffsrechte privilègei oder alle Rechte (ALL PRIVILEGES) auf table oder vue für die Benutzer utilisateuri oder für alle Benutzer (PUBLIC).

Versuchen wir es. Kehren wir zum Editor SQL von ADMIN2 zurück, um die Berechtigung SELECT zu entfernen, die wir dem Benutzer SELECT1 erteilt haben:

Trennen wir die Verbindung des Benutzers SELECT1 und stellen wir sie anschließend wieder her. Fordern wir dann im Editor SQL (SELECT1) den Inhalt der Tabelle TA ab:

Der Benutzer SELECT1 hat tatsächlich sein Leserecht für die Tabelle TA verloren. Es ist zu beachten, dass ADMIN2 ihm dieses Recht erteilt hatte und ADMIN2 es ihm entzogen hat. Wenn ADMIN1 versucht, ihm diese Berechtigung zu entziehen, wird kein Fehler gemeldet, aber anschließend lässt sich feststellen, dass SELECT1 seine Berechtigung SELECT beibehalten hat.

Ein Recht kann allen mit folgender Syntax erteilt werden: GRANT Recht(e) ON Tabelle / Ansicht TO PUBLIC. Vergeben wir also das Recht SELECT für die Tabelle TA an alle. Dazu können wir ADMIN1 oder ADMIN2 verwenden. Wir verwenden ADMIN2:

Erstellen wir eine Verbindung zur Datenbank mit dem Benutzer USER1 / user1:

Öffnen wir mit der Verbindung DBACCES (USER1) einen neuen Editor SQL (Umschalt + F12) und geben wir die folgenden Befehle ein:

Der Benutzer USER1 verfügt tatsächlich über die Berechtigung SELECT für die Tabelle TA.

7.3. Die Transaktionen

7.3.1. Sicherheitsstufen

Wir wenden uns nun vom Thema der Zugriffsrechte auf Datenbankobjekte ab und befassen uns mit dem Thema der gleichzeitigen Zugriffe auf diese Objekte. Zwei Benutzer, die über ausreichende Zugriffsrechte auf ein Datenbankobjekt – beispielsweise eine Tabelle – verfügen, möchten dieses gleichzeitig nutzen. Was passiert dann?

Jeder Benutzer arbeitet innerhalb einer Transaktion. Eine Transaktion ist eine Abfolge von Befehlen SQL, die „atomar“ ausgeführt wird:

  • Entweder werden alle Operationen erfolgreich ausgeführt
  • oder eine davon schlägt fehl, woraufhin alle vorhergehenden rückgängig gemacht werden

Letztendlich wurden die Operationen einer Transaktion entweder alle erfolgreich durchgeführt oder gar keine. Wenn der Benutzer selbst die Kontrolle über die Transaktion hat (was in diesem gesamten Dokument der Fall ist), bestätigt er eine Transaktion mit dem Befehl COMMIT oder bricht sie mit dem Befehl ROLLBACK ab.

Jeder Benutzer arbeitet in einer eigenen Transaktion. Man unterscheidet üblicherweise vier Isolationsstufen zwischen den verschiedenen Benutzern:

  • Uncommitted Read
  • Committed Read
  • Repeatable Read
  • Serialisierbar

Uncommitted Read

Dieser Isolationsmodus wird auch als „Dirty Read“ bezeichnet. Hier ein Beispiel dafür, was in diesem Modus passieren kann:

  1. Ein Benutzer mit dem Namen U1 startet eine Transaktion für die Tabelle T
  2. Ein Benutzer U2 startet eine Transaktion für dieselbe Tabelle T
  3. Der Benutzer U1 ändert Zeilen in der Tabelle T, bestätigt diese jedoch noch nicht
  4. Der Benutzer U2 „sieht“ diese Änderungen und trifft Entscheidungen auf der Grundlage dessen, was er sieht
  5. Der Benutzer bricht seine Transaktion mit einem ROLLBACK ab

Man sieht, dass der Benutzer U2 in Schritt 4 eine Entscheidung auf der Grundlage von Daten getroffen hat, die sich später als falsch herausstellen werden.

Committed Read

Dieser Isolationsmodus vermeidet die oben beschriebene Gefahr. In diesem Modus wird der Benutzer U2 in Schritt 4 die vom Benutzer U1 an der Tabelle T vorgenommenen Änderungen nicht „sehen“. Er wird sie erst sehen, nachdem U1 seine Transaktion mit „COMMIT“ abgeschlossen hat.

In diesem Modus, der auch als „Unrepeatable Read“ bezeichnet wird, können folgende Situationen auftreten:

  1. Ein Benutzer U1 beginnt eine Transaktion auf einer Tabelle T
  2. Ein Benutzer U2 startet eine Transaktion für dieselbe Tabelle T
  3. Der Benutzer U2 führt eine SELECT-Abfrage durch, um den Durchschnitt der Spalte C der Zeilen von T zu ermitteln, die eine bestimmte Bedingung erfüllen
  4. Der Benutzer U1 ändert (UPDATE) bestimmte Werte in Spalte C von T und bestätigt sie (COMMIT)
  5. Der Benutzer U2 führt denselben Vorgang SELECT wie in Schritt 3 erneut durch. Er wird feststellen, dass sich der Durchschnitt der Spalte C aufgrund der von U1 vorgenommenen Änderungen geändert hat.

Nun sieht der Benutzer U2 nur die von U1 „bestätigten“ Änderungen. Doch während er sich noch in derselben Transaktion befindet, liefern zwei identische Operationen (3 und 5) unterschiedliche Ergebnisse. Der Begriff „Unrepeatable Read“ bezeichnet diese Situation. Das ist ärgerlich für jemanden, der sich ein stabiles Abbild der Tabelle T wünscht.

Repeatable Read

In diesem Isolationsmodus ist einem Benutzer garantiert, dass er bei seinen Lesevorgängen aus der Datenbank dieselben Ergebnisse erhält, solange er in derselben Transaktion bleibt. Er arbeitet mit einer Momentaufnahme, in der Änderungen, die durch andere Transaktionen vorgenommen wurden – selbst wenn diese bestätigt wurden –, niemals berücksichtigt werden. Er sieht diese erst, wenn er selbst seine Transaktion mit einem COMMIT oder ROLLBACK abschließt.

Dieser Isolationsmodus ist jedoch noch nicht perfekt. Nach dem oben genannten Schritt 3 sind die vom Benutzer U2 abgefragten Zeilen gesperrt. Bei Vorgang 4 kann der Benutzer U1 die Werte in Spalte C dieser Zeilen nicht ändern (UPDATE). Er kann jedoch Zeilen hinzufügen (INSERT). Wenn einige der hinzugefügten Zeilen die in Schritt 3 geprüfte Bedingung erfüllen, ergibt Schritt 5 aufgrund der hinzugefügten Zeilen einen anderen Durchschnittswert als den in Schritt 3 ermittelten.

Um dieses neue Problem zu beheben, muss auf die Isolationsstufe „Serializable“ umgestellt werden.

Serializable

In diesem Isolationsmodus sind die Transaktionen vollständig voneinander abgeschottet. Er stellt sicher, dass das Ergebnis zweier gleichzeitig durchgeführter Transaktionen dasselbe ist, als wären sie nacheinander ausgeführt worden. Um dieses Ergebnis zu erreichen, wird der Benutzer U1 bei Operation 4 daran gehindert, Zeilen hinzuzufügen, die das Ergebnis von SELECT des Benutzers U1 verändern würden. Eine Fehlermeldung weist ihn darauf hin, dass das Einfügen nicht möglich ist. Dies wird erst möglich, wenn der Benutzer U2 seine Transaktion bestätigt hat.

Die vier Transaktionsisolationsstufen SQL sind nicht in allen SGBD verfügbar. Firebird bietet die folgenden Isolationsstufen:

  • snapshot: Standard-Isolationsmodus. Entspricht dem Modus „Repeatable Read“ des Standards SQL.
  • committed read: entspricht dem Modus „committed read“ des Standards SQL

Diese Isolationsstufe wird durch den Befehl SET TRANSACTION festgelegt:

syntaxe
SET TRANSACTION
[READ WRITE | READ ONLY]
[WAIT|NOWAIT]
ISOLATION LEVEL [SNAPSHOT | READ COMMITTED]
fonctionnement
Die unterstrichenen Schlüsselwörter sind die Standardwerte
READ WRITE: Die Transaktion kann lesen und schreiben
READ ONLY: Die Transaktion kann nur lesen
WAIT: Bei einem Konflikt zwischen zwei Transaktionen wartet diejenige, die ihre Operation nicht ausführen konnte, bis die andere Transaktion bestätigt wurde. Sie kann keine Befehle mehr senden (SQL).
NOWAIT: Die Transaktion, die ihre Operation nicht ausführen konnte, wird nicht blockiert. Sie erhält eine Fehlermeldung und kann ihre Arbeit fortsetzen.
ISOLATION LEVEL [SNAPSHOT | READ COMMITTED]: Isolationsstufe

Versuchen wir es. Im Editor SQL (ADMIN1) geben wir den folgenden Befehl SQL ein:

Image

Wir sehen, dass er nicht zugelassen wurde. Wir wissen nicht, warum...

Mit IB-Expert lässt sich der Isolationsmodus auf andere Weise festlegen. Klicken wir mit der rechten Maustaste auf die Verbindung DBACCES(ADMIN1), um die Option [Database Registration Info] auszuwählen:

Der Bildschirm auf der rechten Seite zeigt, dass eine Option [Transactions] vorhanden ist. Mit ihr können wir den Isolationsgrad der Transaktionen festlegen. Wir legen ihn hier auf [snapshot] fest. Das Gleiche tun wir mit der Verbindung DBACCES (ADMIN2).

7.3.2. Der Snapshot-Modus

Betrachten wir die Isolationsstufe snapshot, die den Standard-Isolationsmodus von Firebird darstellt. Wenn der Benutzer eine Transaktion startet, wird eine Momentaufnahme der Datenbank erstellt. Der Benutzer arbeitet dann mit dieser Momentaufnahme. Jeder Benutzer arbeitet somit an einem eigenen Snapshot der Datenbank. Wenn er Änderungen daran vornimmt, sind diese für andere Benutzer nicht sichtbar. Sie werden erst sichtbar, wenn der Benutzer, der die Änderungen vorgenommen hat, diese mit einem COMMIT bestätigt hat.

Es sind zwei Fälle zu unterscheiden:

  • Ein Benutzer liest die Tabelle (SELECT), während ein anderer sie gerade bearbeitet (INSERT, UPDATE, DELETE)
  • Beide Benutzer möchten die Tabelle gleichzeitig ändern

7.3.2.1. Prinzip des konsistenten Lesens

Nehmen wir zwei Benutzer U1 und U2 an, die an derselben Tabelle TAB arbeiten:

      --------+----------+--------+-------+----------------------
              T1a       T2a      T1b     T2b 

Die Transaktion des Benutzers U1 beginnt zum Zeitpunkt T1a und endet zum Zeitpunkt T1b.

Die Transaktion des Benutzers U2 beginnt zum Zeitpunkt T2a und endet zum Zeitpunkt T2b.

U1 bearbeitet ein Foto von TAB, das zum Zeitpunkt T1a aufgenommen wurde. Zwischen T1a und T1b bearbeitet er TAB. Die anderen Benutzer haben erst zum Zeitpunkt T1b Zugriff auf diese Änderungen, wenn U1 ein COMMIT erstellt.

U2 bearbeitet ein Foto von TAB, das zum Zeitpunkt T2a aufgenommen wurde, also dasselbe Foto, das auch von U1 verwendet wurde (sofern andere Benutzer das Original in der Zwischenzeit nicht geändert haben). Er „sieht“ die Änderungen nicht, die der Benutzer U1 an TAB vorgenommen hat. Er kann sie erst zum Zeitpunkt T1b sehen.

Veranschaulichen wir diesen Punkt anhand unserer Datenbank [DBACCES]. Wir lassen die beiden Benutzer [ADMIN1] und [ADMIN2] gleichzeitig arbeiten. Wechseln wir zur Verbindung DBACCES (ADMIN1) und führen wir im Editor SQL von ADMIN1 die folgenden Schritte durch:

ADMIN1 hat Zeile Nr. 2 der Tabelle TA geändert, seinen Vorgang jedoch noch nicht freigegeben (COMMIT). Der Benutzer ADMIN2 führt daraufhin einen SELECT in der Tabelle TA durch (man gelangt vom Editor ADMIN2 in den Editor SQL). Wir befinden uns vor dem Zeitpunkt T2a des Beispiels.

Zurück zum Editor SQL von ADMIN1, der die Hinzufügung bestätigt:

 

Zurück zum Editor SQL von ADMIN2, um SELECT erneut zu erstellen:

ADMIN2 sieht die von ADMIN1 vorgenommenen Änderungen. Im Snapshot-Modus sieht eine Transaktion die von anderen Transaktionen vorgenommenen Änderungen erst, wenn diese abgeschlossen sind.

7.3.2.2. Gleichzeitige Änderung desselben Datenbankobjekts durch zwei Transaktionen

Nehmen wir ein Beispiel aus der Buchhaltung: U1 und U2 bearbeiten Konten. U1 belastet comptex mit einem Betrag S und schreibt denselben Betrag comptey gut. Dies erfolgt in mehreren Schritten:

      --------+----------+--------+-------+----------------------
              T1a       T1b     T1c      T1d 

U1 startet eine Transaktion zum Zeitpunkt T1a, belastet comptex zum Zeitpunkt T1b, schreibt den Betrag comptey zum Zeitpunkt T1c gut und bestätigt beide Vorgänge zum Zeitpunkt T1d. Nehmen wir außerdem an, dass U2 dasselbe tun möchte, seine Transaktion zum Zeitpunkt T2a beginnt und sie zum Zeitpunkt T2d gemäß dem folgenden Schema beendet:

      --------+----------+----+----+-------+------+-----+-------+---------
              T1a       T1b  T2a   T1c     T2b   T1d   T2c    T2d

Zum Zeitpunkt T2 wird eine Momentaufnahme der Kontentabelle für U2 erstellt. Diese ist gemäß dem Prinzip von snapshot konsistent. U2 sieht den Ausgangszustand der Konten comptex und comptey, da U1 seine Vorgänge noch nicht freigegeben hat.

Nehmen wir an, dass comptex einen Anfangssaldo von 1000 € hat und dass die Benutzer U1 und U2 jeweils 100 € von diesem Konto abbuchen möchten.

  • Zum Zeitpunkt T1b verringert U1 den Kontostand von comptex um 100 € und setzt ihn somit auf 90 €. Diese Transaktion wird erst zum Zeitpunkt T1d bestätigt.
  • Zum Zeitpunkt T2b sieht U2, dass comptex 1000 € aufweist (Prinzip der konsistenten Lesezugriffe), verringert dessen Wert um 100 € und setzt ihn somit auf 90 €.
  • Letztendlich wird comptex zum Zeitpunkt T2d, wenn alles validiert wurde, einen Saldo von 90 € statt der erwarteten 80 € aufweisen.

Die Lösung für dieses Problem besteht darin, zu verhindern, dass U2 comptex ändert, solange U1 seine Transaktion nicht abgeschlossen hat. U2 wird somit bis zum Zeitpunkt T1d gesperrt. Der Modus snapshot stellt diesen Mechanismus bereit.

Veranschaulichen wir dies anhand der Datenbank DBACCES. ADMIN1 beginnt eine Transaktion in seinem Editor SQL (ADMIN1):

Zunächst haben wir einen COMMIT erstellt, um sicherzustellen, dass eine neue Transaktion gestartet wird. Anschließend haben wir Zeile Nr. 4 gelöscht. Die Transaktion wurde noch nicht freigegeben.

ADMIN2 startet seinerseits eine Transaktion in seinem Editor SQL (ADMIN2):

Der Bildschirm auf der rechten Seite zeigt, dass ADMIN2 die Zeile Nr. 4 ändern wollte. Es wurde ihm mitgeteilt, dass dies nicht möglich sei, da jemand anderes die Zeile bereits geändert, diese Änderung jedoch noch nicht freigegeben habe.

Kehren wir zum Editor SQL (ADMIN1) zurück, um den Eintrag COMMIT zu erstellen:

Image

Kehren wir zum Editor SQL(ADMIN2) zurück, um den Befehl UPDATE erneut auszuführen:

Der Vorgang UPDATE verläuft erfolgreich, obwohl Zeile Nr. 4 nicht mehr existiert, wie der nachfolgende SELECT zeigt. Zu diesem Zeitpunkt stellt ADMIN2 fest, dass die Zeile nicht mehr existiert.

7.3.2.3. Der Modus „Repeatable Read“

Veranschaulichen wir nun den Modus „Repeatable Read“. Diese Isolationsstufe wird durch den „Snapshot“-Modus bereitgestellt. Er stellt sicher, dass eine Transaktion beim Lesen der Datenbank immer das gleiche Ergebnis erhält.

Beginnen wir mit dem Editor SQL von ADMIN2:

Kommen wir nun zum Editor SQL von ADMIN1:

 

Der Benutzer ADMIN1 hat zwei Zeilen hinzugefügt und seine Transaktion bestätigt. Kehren wir nun zum Editor SQL (ADMIN2) zurück, um den Vorgang SELECT SUM erneut auszuführen:

Man sieht, dass ADMIN2 die Zeilenergänzungen aus ADMIN1 nicht berücksichtigt, obwohl diese durch ein COMMIT validiert wurden. SELECT SUM liefert dasselbe Ergebnis wie vor den Einfügungen. Das ist das Prinzip des „Repeatable Read“.

Nun, immer noch im Editor SQL (ADMIN2), bestätigen wir die Transaktion mit einem COMMIT und führen dann den SELECT SUM erneut aus:

Die von ADMIN1 hinzugefügten Zeilen werden nun berücksichtigt.

7.3.3. Der Modus „Committed Read“

Veranschaulichen wir nun den Modus „Committed Read“. Diese Isolationsstufe entspricht der von snapshot, mit Ausnahme des „Repeatable Read“.

Zunächst ändern wir die Isolationsstufe der Transaktionen beider Verbindungen.

  • Wir trennen die Verbindung der beiden Benutzer ADMIN1 und ADMIN2
  • Wir ändern die Isolationsstufe ihrer Transaktionen

Image

  • Wir stellen die Verbindung für die Benutzer ADMIN1 und ADMIN2 wieder her

Wir greifen nun das vorherige Beispiel wieder auf, das den „Repeatable Read“ veranschaulichte, um zu zeigen, dass wir nicht mehr dasselbe Verhalten haben. Beginnen wir damit, mit dem Editor SQL von ADMIN2 zu arbeiten:

Kommen wir nun zum Editor SQL von ADMIN1:

 

Der Benutzer ADMIN1 hat zwei Zeilen hinzugefügt und seine Transaktion bestätigt. Kehren wir nun zum Editor SQL (ADMIN2) zurück, um den Vorgang SELECT SUM erneut auszuführen:

Der SELECT SUM liefert nicht dasselbe Ergebnis wie vor den Ergänzungen durch ADMIN1. Das ist der Unterschied zwischen den Modi „Snapshot“ und „Read Committed“.