Worum es geht
Eine Transaktion ist eine Klammer um Änderungen in der Datenbank: Entweder werden alle Änderungen darin dauerhaft, oder keine. Das Dauerhaft-Machen heißt Commit, das Verwerfen heißt Rollback.
In CDMS ist diese Klammer genau eine Anfrage. Alles, was eine Anfrage schreibt, gehört zusammen: das Objekt selbst, alle verschachtelten Kinder, alle mitgelöschten Objekte und alles, was Hooks über CDMS schreiben.
Der Zeitstrahl einer Anfrage
sequenceDiagram
participant C as Client
participant D as CDMS
participant H as Hook
participant DB as Datenbank
C->>D: PUT /company/update/c4…
D->>DB: erste Datenbankaktion öffnet die Transaktion
D->>H: Before-Hooks
D->>DB: ändern, Kinder schreiben
D->>H: After-Hooks
D->>DB: flush: SQL wird ausgeführt, noch nicht festgeschrieben
D->>DB: zurücklesen für die Antwort
D->>DB: COMMIT
D-->>C: 200 mit dem Objekt
Zwei Zeitpunkte muss man auseinanderhalten:
- flush: CDMS schickt die gesammelten SQL-Befehle an die Datenbank. Die Datenbank prüft dabei ihre Regeln, zum Beispiel eindeutige Werte. Andere Anfragen sehen die Änderung noch nicht.
- Commit: Die Datenbank macht die Änderung dauerhaft und für alle sichtbar. Das passiert direkt, bevor CDMS die Antwort schreibt.
Kommt beim Client eine Erfolgsantwort an, ist die Änderung also schon gespeichert. Eine Anfrage direkt danach sieht sie.
Erfolg, Fehler, Konflikt
Wann: Alle Schritte gelingen.
-
1CDMSverarbeitet die Anfrage: prüfen, schreiben, Hooks, zurücklesen
-
2CDMS→DatabaseCommit, unmittelbar bevor der Antwortkörper geschrieben wird
-
3CDMS→Client2xx
Ergebnis: Die Änderung ist dauerhaft.
Wann: Irgendein Schritt scheitert: Rolle fehlt, Validierung, Hook, Datenbankregel.
-
1CDMSein Schritt wirft einen Fehler
-
2CDMS→Databasemarkiert die ganze Anfrage als gescheitert und rollt alle offenen Transaktionen zurück
-
3CDMS→ClientFehlerantwort, z. B. 400, 403, 404, 422
Ergebnis: Nichts von dieser Anfrage ist gespeichert, auch nicht die Teile, die vor dem Fehler schon geschrieben waren.
Wann: Alle Schritte gelingen, aber eine andere Anfrage hat dasselbe Datei-Modell gleichzeitig geändert. Nur Datei-Modelle erkennen gleichzeitige Änderungen.
-
1CDMS→DatabaseCommit scheitert an der gleichzeitigen Änderung
-
2CDMS→Client409, die Anfrage wird zurückgerollt
Ergebnis: Weil der Commit vor der Antwort liegt, erfährt der Client davon. Siehe Gleichzeitige Änderungen.
Entscheidungstabelle
| Alle Schritte erfolgreich? | Commit erfolgreich? | Ergebnis |
|---|---|---|
| ja | ja | 2xx, alles gespeichert |
| ja | nein | 409 bei gleichzeitiger Änderung eines Datei-Modells, sonst ein Serverfehler; nichts gespeichert |
| nein | – | Fehlerantwort; nichts gespeichert |
Zwei Fälle haben eigene Seiten:
- Inhalte im Dateispeicher gehören nicht zur Transaktion, folgen ihr aber: Sie werden erst nach dem Commit wirksam. Dateien und Transaktion
- Eine Anfrage, die System- und Mandanten-Modelle schreibt, hat zwei Transaktionen: Keine Atomarität über zwei Datenbanken
Was alles in der Klammer liegt
| Was | in derselben Transaktion? |
|---|---|
| das Objekt der Anfrage | ja |
| verschachtelt angelegte, geänderte oder gelöschte Kinder | ja |
| abgekoppelte Objekte (Verweis geleert) | ja |
| Schreibzugriffe eines Hooks über CDMS auf Modelle derselben Ebene | ja |
| das Zurücklesen für die Antwort | ja, im Modus STRICT |
| Dateiinhalte im Dateispeicher | nein, aber sie werden erst nach dem Commit wirksam und bei einem Fehler verworfen |
| E-Mails, HTTP-Aufrufe, Nachrichten, die ein Hook verschickt | nein |
Zwei Anfragen, zwei Transaktionen
-
1Client→CDMS
POST /customer/create→ 200, der Kunde ist gespeichert -
2Client→CDMS
POST /order/createmit dem neuen Kunden → 422 -
3CDMSrollt nur die zweite Anfrage zurückErgebnis: Der Kunde bleibt, obwohl sein Auftrag fehlt.
Eine Klammer über mehrere Anfragen gibt es nicht. Wenn zwei Objekte nur gemeinsam entstehen dürfen, schreibe sie in einer Anfrage, verschachtelt über die Beziehung. Siehe Die vier Fälle beim verschachtelten Schreiben.
Fallen
Wie es weitergeht
- Was passiert, wenn nach dem Anlegen das Zurücklesen scheitert: Anlegen und Zurücklesen: STRICT oder LENIENT
- Ob der Client nach einem Fehler wiederholen darf: Darf der Client wiederholen?
- Der Weg einer Anfrage durch die Schichten: Der Weg einer Anfrage durch die Schichten