WEBVTT

00:00.440 --> 00:03.440
So, heute haben wir ein Mammutprogramm vor uns.

00:04.360 --> 00:06.900
Zweimal jede eineinhalb Stunden.

00:07.400 --> 00:11.600
Jetzt schließen wir erstmal noch die Normalisierung ab.

00:12.200 --> 00:16.260
Und ich erinnere nochmal daran, gestern haben wir im Wesentlichen

00:16.260 --> 00:19.960
angesehen, einmal die Frage, oder versucht die Frage zu beantworten,

00:20.680 --> 00:24.140
welche Zerlegungen gut sind.

00:30.900 --> 00:34.120
Also einmal diese Frage hier, welche sind gut.

00:35.600 --> 00:41.200
Und um solche Qualitätsmaßstäbe, formale Qualitätsmaßstäbe zu

00:41.200 --> 00:47.480
entwickeln, haben wir uns an den Anomalien orientiert, die ihrerseits

00:47.480 --> 00:49.760
dadurch bedingt sind, dass wir Redundanzen mitschleppen.

00:50.140 --> 00:54.500
Und wir haben festgestellt, dass wir die Redundanzen dann eliminieren

00:54.500 --> 00:57.960
können, wenn wir einmal die mehrwertigen Abhängigkeiten entfernen und

00:57.960 --> 01:00.740
zum Zweiten, wenn wir die funktionalen Abhängigkeiten auf

01:00.740 --> 01:02.440
Schlüsselabhängigkeiten zurückführen.

01:02.960 --> 01:07.200
Und das ist uns auch gelungen, bis zur dritten Normalform.

01:07.880 --> 01:13.160
Und danach wurde es etwas schwieriger bei der BCNF und 4NF, die auch

01:13.160 --> 01:16.320
diesen Kriterien unterworfen sind, war das nicht mehr so

01:16.320 --> 01:18.800
offensichtlich, dass das an den Beispielen zumindest gelang.

01:19.720 --> 01:22.460
Dann haben wir die zweite Frage gestellt, was ist korrekt?

01:22.460 --> 01:24.480
Welche Zerlegungen sind korrekt?

01:25.000 --> 01:28.040
Und da haben wir festgestellt, dass wir zwei Bedingungen zu erfüllen

01:28.040 --> 01:31.780
haben, nämlich die Verlustlosigkeit, die Verlustlosigkeit besagt, dass

01:31.780 --> 01:37.560
wenn ich mir als Benutzer eine Relation R vorstelle, intern wird sie

01:37.560 --> 01:41.720
zerlegt in eine Reihe von Relationen, die irgendwelchen Normalformen

01:41.720 --> 01:46.020
gehorchen, zum Beispiel der dritten Normalform oder BCNF, dann muss

01:46.020 --> 01:50.500
ich wieder die ursprüngliche Datenbasis herstellen können, das heißt

01:50.500 --> 01:53.100
mit anderen Worten, es dürfen nicht plötzlich in der Datenbasis

01:53.100 --> 01:58.460
Zustände auftauchen, die nach dem Verhalten nach außen der Relation R

01:58.460 --> 01:59.900
dort nicht auftreten dürfen.

02:01.280 --> 02:08.260
Das war die Abhängigkeitsbewahrung, da sind keine falschen Zustände

02:08.260 --> 02:11.720
uns plötzlich reingeraten und verlustlos hieß umgekehrt, das war auch

02:11.720 --> 02:15.920
jeden der Zustand, der legitim war in unserer Relation R und

02:15.920 --> 02:18.820
infolgedessen auch durch Eingaben erzeugt werden konnte oder durch

02:18.820 --> 02:22.680
Änderungsanweisungen, dass der auch tatsächlich hinterher wieder im

02:22.680 --> 02:26.560
Ergebnis bei der Zusammensetzung über die Verbindungsoperation wieder

02:26.560 --> 02:28.680
auftauchen sollte, das war die Verlustlosigkeit.

02:28.860 --> 02:32.500
Wir hatten festgestellt, dass im Grunde genommen beide Eigenschaften

02:32.500 --> 02:36.960
gemeinsam, und beide sind ja wünschenswert, dass beide gemeinsam nur

02:36.960 --> 02:42.920
dann auftreten, wenn exakt die Relation R, die wir nach außen sehen,

02:43.260 --> 02:47.740
identisch ist mit der Verbindung aller Relationen, die aus der

02:47.740 --> 02:49.160
Zerlegung hervorgegangen sind.

02:53.060 --> 02:56.240
Jetzt, offensichtlich sind wir da über irgendwelche Folien verloren

02:56.240 --> 03:01.820
gegangen, man kann nämlich jetzt folgendes nachweisen, dass bis zur

03:01.820 --> 03:06.960
dritten Normalform ist die Verlustlosigkeit und die

03:06.960 --> 03:10.460
Abhängigkeitsbewahrung gleichermaßen gewährleistet.

03:11.340 --> 03:13.400
Und wenn wir darüber hinaus gehen, dann müssen wir Kompromisse

03:13.400 --> 03:15.400
eingehen, dann müssen wir auf eine der beiden Eigenschaften

03:15.400 --> 03:15.900
verzichten.

03:17.780 --> 03:21.020
Die dritte Frage, die wir dann stellen müssen, ist schließlich, wie

03:21.020 --> 03:24.000
findet man nun, jetzt nachdem wir wissen, was gute und korrekte

03:24.000 --> 03:25.440
Zerlegungen sind, wie findet man die?

03:27.320 --> 03:31.080
Und da gibt es erfreulicherweise einen Zerlegungsalgorithmus.

03:31.080 --> 03:34.160
Wenn man den anwendet, und den kann man umsetzen, also steckt man am

03:34.160 --> 03:37.260
Schluss nur noch unsere Relation R rein und die funktionalen und

03:37.260 --> 03:39.460
mehrwertigen Abhängigkeiten, in dem Fall eigentlich nur die

03:39.460 --> 03:43.240
funktionalen Abhängigkeiten, dann liefert uns der anschließend eine

03:43.240 --> 03:45.480
Zerlegung in die 3NF.

03:48.100 --> 03:52.420
So, hier steht es nochmal, nämlich die Resultate besagen folgendes,

03:52.420 --> 03:55.680
wenn wir uns also einen Relationstyp R vorgeben, das ist also der, den

03:55.680 --> 04:01.260
wir nach außen präsentieren, und wir haben eine Menge von funktionalen

04:01.260 --> 04:03.080
Abhängigkeiten, wir betrachten jetzt nur die funktionalen

04:03.080 --> 04:11.040
Abhängigkeiten, dann gilt folgendes, wir können eine verlustlose, aber

04:11.040 --> 04:15.540
nicht notwendig abhängigkeitsbewahrende Zerlegung in eine Menge von

04:15.540 --> 04:17.680
Relationstypen in BCNF geben.

04:18.560 --> 04:24.660
Wir können verlustlos und abhängigkeitsbewahrend in Relationstypen in

04:24.660 --> 04:29.860
3NF angeben und wir können jeweils polynomiale Algorithmen angeben,

04:29.960 --> 04:31.160
die diese Zerlegung finden.

04:32.100 --> 04:34.380
Also müssen wir uns die Frage stellen, wie weit wollen wir gehen?

04:35.000 --> 04:39.400
Wollen wir bis zur BCNF gehen und damit auch die funktionalen

04:39.400 --> 04:42.300
Abhängigkeiten, die sie nicht in Schlüsselbedingungen überführen

04:42.300 --> 04:45.820
lassen, noch durch Zerlegung in Schlüsselbedingungen überführen?

04:46.300 --> 04:50.640
Oder bleiben wir bei der dritten Normalform, bei der wir zugleich auch

04:50.640 --> 04:53.400
noch die Abhängigkeitsbewahrung garantieren können?

04:54.440 --> 04:58.020
Also angenommen, Sie hätten jetzt einen Algorithmus zu entwickeln, Sie

04:58.020 --> 05:00.980
müssen sich entscheiden, ob Sie bis zur dritten Normalform oder bis

05:00.980 --> 05:02.720
zur BCNF gehen, wie weit würden Sie denn gehen?

05:05.140 --> 05:07.220
Wer würde nur bis zur dritten Normalform gehen?

05:09.700 --> 05:11.420
Alle würden bis zur BCNF gehen?

05:11.420 --> 05:16.840
Das heißt, Sie verzichten darauf oder Sie akzeptieren, dass Ihnen auch

05:16.840 --> 05:23.060
inkorrekte, also inkonsistente Werte, zwar nicht in die zerlegten

05:23.060 --> 05:25.400
Relationen, aber sehr wohl in das Gesamtergebnis, wenn Sie Ihre Joint

05:25.400 --> 05:29.860
-Operationen durchführen, in das Ergebnis mit reinutschen würden?

05:30.360 --> 05:32.600
Würden Sie wirklich inkonsistente Ergebnisse akzeptieren?

05:35.060 --> 05:36.420
Also ich würde das nicht tun.

05:37.340 --> 05:41.060
Ich würde nur bis zur dritten Normalform gehen, dann weiß ich ja

05:41.060 --> 05:44.760
inzwischen, dass ich in SQL 99 auch Konsistenzbedingungen angeben

05:44.760 --> 05:50.120
kann, also könnte ich insbesondere die FDs, die ich nicht in

05:50.120 --> 05:53.080
Schlüsselbedingungen überführen kann, die würde ich dann auch noch als

05:53.080 --> 05:55.340
zusätzliche Konsistenzbedingungen formulieren.

05:56.520 --> 05:58.260
Also ich würde nur bis zur dritten Normalform gehen.

05:58.580 --> 06:00.000
Und der Meinung sind so ziemlich alle.

06:02.920 --> 06:07.140
Wenn wir auch noch MVDs haben, dann haben wir das Problem, dass wir in

06:07.140 --> 06:11.160
die vierte Normalform übergehen müssen und jetzt lautet die vierte

06:11.160 --> 06:15.780
Normalform in ihrer Bedingung besagt ja, dass sie noch die BZNF weiter

06:15.780 --> 06:19.460
einengt, also wissen wir von vornherein, dass wir vierte Normalform im

06:19.460 --> 06:23.240
Allgemeinfall, nicht im Speziellen, aber im Allgemeinfall auch nur

06:23.240 --> 06:27.740
entweder verlustlos oder abhängigkeitsbewahrend realisieren können,

06:27.740 --> 06:31.740
oder zerlegen können und infolgedessen gilt halt genau das gleiche.

06:33.060 --> 06:39.160
Wir werden auf Verlustlosigkeit gehen, das heißt, da habe ich vorhin

06:39.160 --> 06:42.720
falsch gesagt, Verlustlosigkeit heißt also, dass wir auf jeden Fall

06:42.720 --> 06:46.880
die Eingaben, die gerecht sind, dass die Ergebnisse auch wieder

06:46.880 --> 06:49.900
rekonstruierbar sind und das einzige, was wir akzeptieren müssen, ist,

06:50.020 --> 06:54.360
dass gelegentlich eben noch fehlerhafte Ergebnisse mitproduziert

06:54.360 --> 06:57.400
werden und die können wir verhindern, indem wir eben zusätzliche

06:57.400 --> 06:58.680
Konsistenzbedingungen anwenden.

06:59.840 --> 07:01.920
Wir werden hinterher überlegen müssen, wo werden diese

07:01.920 --> 07:03.380
Konsistenzbedingungen nachher ausgeführt.

07:03.460 --> 07:05.780
Wir müssen uns ja Folgendes vorstellen, nach außen hin haben wir

07:05.780 --> 07:12.820
unsere Relation R, diese Relation R, für die definieren wir auch ein

07:12.820 --> 07:15.300
Schema, da können wir also die Konsistenzbedingungen formulieren,

07:15.460 --> 07:17.980
intern haben wir aber nur die zerlegten Relationen, also müssen wir

07:17.980 --> 07:21.480
fragen, wo werden denn eigentlich jetzt diese Konsistenzbedingungen

07:21.480 --> 07:22.080
überprüft.

07:22.080 --> 07:24.720
Da erinnern wir uns noch an unsere Architektur, da haben wir gesagt,

07:24.780 --> 07:27.960
das machen wir relativ weit oben, nämlich auf der obersten Schicht.

07:29.280 --> 07:33.100
Also ist die Zerlegung zumindest mal eine interne Maßnahme, die müssen

07:33.100 --> 07:34.320
wir nicht unbedingt nach außen zeigen.

07:36.960 --> 07:40.440
So, also in der Praxis zerlegt man normalerweise nur bis zur dritten

07:40.440 --> 07:45.760
Normalform und dann wissen wir also, dass Folgendes gilt, dass diese

07:45.760 --> 07:52.280
Bedingung hier erfüllt ist, aber dass wir dabei gewisse Bedingungen

07:52.280 --> 08:00.140
aus Sigma, dass also die Hülle über den zerlegten Relationen

08:00.840 --> 08:04.520
möglicherweise nur eine Teilmenge ist, der Sigma Hülle, Sigma Plus

08:04.520 --> 08:06.520
über der Gesamtrelation.

08:11.350 --> 08:12.770
So, wie sieht jetzt der Algorithmus aus?

08:14.070 --> 08:18.130
Der ist eigentlich ziemlich einfach, der besagt nämlich Folgendes, wir

08:18.130 --> 08:24.230
arbeiten wieder mit unserer kanonischen Überdeckung, Sigma C.

08:24.830 --> 08:27.370
Also wir minimieren wieder die funktionalen Abhängigkeiten, Sie

08:27.370 --> 08:30.970
erinnern sich noch, am besten starten wir mit den vollfunktionalen

08:30.970 --> 08:33.670
Abhängigkeiten, dann können wir uns diese ersten Schritte ersparen für

08:33.670 --> 08:38.130
die kanonische Überdeckung und dann fassen wir nur noch die gleichen

08:38.130 --> 08:42.610
linken Seiten zusammen, das heißt wir expandieren dann die rechten

08:42.610 --> 08:43.010
Seiten.

08:43.010 --> 08:49.150
Und jetzt gilt noch folgendes, damit wir möglichst viele unserer

08:49.150 --> 08:55.570
funktionalen Abhängigkeiten in einer Relation fangen, müssen wir noch

08:55.570 --> 08:57.690
die funktionalen Abhängigkeiten ordnen.

08:57.930 --> 09:01.590
Und wir ordnen sie so, dass wir nach der Anzahl der Attribute

09:01.590 --> 09:02.490
sortieren.

09:02.970 --> 09:06.210
Das heißt, wir nehmen unser Sigma C, das ja bis jetzt ungeordnet war,

09:06.210 --> 09:11.230
und ordnen es noch nachträglich, und zwar nach der Zahl der Attribute,

09:11.650 --> 09:15.210
die in der funktionalen Abhängigkeit vorkommen.

09:15.630 --> 09:18.570
Und das bedeutet einfach, wie wir gleich sehen werden, wir beginnen

09:18.570 --> 09:21.230
mit der ersten funktionalen Abhängigkeit, versuchen dann eine Relation

09:21.230 --> 09:24.850
draus zu machen und fahren sofort, und dann kann man nicht

09:24.850 --> 09:27.610
feststellen, wenn zum Beispiel weitere funktionale Abhängigkeiten

09:27.610 --> 09:32.650
existieren, deren Attribute Teilmengen in einer Relation sind, die

09:32.650 --> 09:35.770
bereits eingerichtet, die bereits definiert worden ist, dann fällt die

09:35.770 --> 09:41.350
einfach mit in diese spezifische Relation mit hinein, während wenn wir

09:41.350 --> 09:43.790
mit einer kleinen Relation beginnen würden, und wir würden größere

09:43.790 --> 09:46.330
entwickeln, dann würden wir zusätzliche Relationen einführen, würden

09:46.330 --> 09:48.950
feststellen, dass hinterher eine Menge Redundanzen entstanden sind,

09:49.610 --> 09:52.430
quer über Relationen hinweg müssten wir nochmal eine Bereinigungsphase

09:52.430 --> 09:52.930
einrichten.

09:53.170 --> 09:57.510
Also das hat nur damit zu tun, dass wir durch die Ordnung mit einer

09:57.510 --> 10:01.670
minimalen Zahl von Relationen der Zerlegung enden.

10:01.670 --> 10:04.590
So, wenn wir uns jetzt also vorstellen, dass wir die geordnet haben,

10:04.990 --> 10:10.090
dann gilt folgendes, wir bilden für jede funktionale Abhängigkeit, die

10:10.090 --> 10:19.070
wir jetzt in dieser kanonischen Bedeckung finden, dieser geordneten,

10:19.450 --> 10:21.670
bilden wir eben einen eigenen Relationstyp.

10:22.550 --> 10:27.070
Und zwar immer dann, sofern eben nicht die Menge der Attribute, die in

10:27.070 --> 10:30.970
dieser FD stecken, nicht bereits Teil einer anderen Relation sind.

10:30.970 --> 10:35.910
Das funktioniert jetzt bequem, weil wir eben diese Ordnung in der

10:35.910 --> 10:38.030
kanonischen Überdeckung vorgenommen haben.

10:38.210 --> 10:42.370
Also da kann natürlich passieren, dass wir nochmal eine FD finden, die

10:42.370 --> 10:46.470
bereits in einer Relation drinsteckt, die wir definiert haben.

10:47.090 --> 10:50.050
Und dann müssen wir natürlich diese Sigma irgendwie dahin zuschlagen.

10:52.070 --> 10:52.890
Jetzt fangen wir also an.

10:54.430 --> 10:57.690
Das war jetzt also die Idee, wir kommen von oben, nehmen uns die erste

10:57.690 --> 11:02.290
FD in der Überdeckung vor und wiederholen das Ganze.

11:03.250 --> 11:06.670
Das heißt, wir arbeiten jetzt durch, alle diese funktionalen

11:06.670 --> 11:13.970
Abhängigkeiten durch und wir prüfen jetzt, wenn in den bisher

11:13.970 --> 11:20.810
erzeugten Relationen die Menge, die Vereinigung der XY noch nicht

11:20.810 --> 11:27.310
vorkommt, wenn sie vorkommt, dann haben wir bereits eine geeignete

11:27.310 --> 11:28.270
Relation vor uns.

11:28.670 --> 11:32.790
Was wir noch nicht haben, in diesem Fall, ist diese zusätzliche

11:32.790 --> 11:36.330
funktionale Abhängigkeit, die wir jetzt dem Sigma I dieser

11:36.330 --> 11:38.770
spezifischen Relation zuschlagen müssen.

11:39.210 --> 11:44.070
Also wenn wir eine Relation finden, hier heißt es RJ, in der die

11:44.070 --> 11:46.570
Attribute unserer funktionalen Abhängigkeit, die wir gerade

11:46.570 --> 11:49.950
herausgegriffen haben, schon vorkommt, dann schlagen wir einfach diese

11:49.950 --> 11:56.490
funktionale Abhängigkeit der Menge der FDs für diese spezifische

11:56.490 --> 11:57.830
Relation RJ hinzu.

11:58.510 --> 12:05.530
Wenn das nicht der Fall ist, dann bilden wir eine neue Relation mit

12:05.530 --> 12:12.230
den Attributen X und Y und wir schlagen natürlich die FD als die erste

12:12.230 --> 12:18.330
FD der Menge der FDs für diese neue Relation RI zu.

12:19.090 --> 12:22.270
Und so, wenn Sie sich vorstellen, jetzt laufen wir also durch, und

12:22.270 --> 12:27.990
jede funktionale Abhängigkeit wird entweder überführt in eine neue

12:27.990 --> 12:31.330
Relation oder sie wird einer vorhandenen Relation als neue FD

12:31.330 --> 12:32.050
hinzuschlagen.

12:32.290 --> 12:35.530
Und da ist natürlich durchaus möglich, dass wir insbesondere auch noch

12:35.530 --> 12:39.970
FDs finden, die von der Bauart sind, dass auf der rechten Seite

12:39.970 --> 12:41.270
Schlüsselattribute stehen.

12:41.970 --> 12:45.010
Das heißt, es ist durchaus denkbar, dass auf die Art Relationen

12:45.010 --> 12:48.130
entstehen, die nicht in BCNF sind.

12:48.470 --> 12:50.710
Aber sie sind, das garantieren wir, in 3NF.

12:50.890 --> 12:51.970
Und so weit wollten wir ja nur gehen.

12:54.230 --> 12:57.690
Jetzt ist ja immer so, dass wir am Ende, oder dass wir sicherstellen

12:57.690 --> 13:03.590
müssen, dass wir die Gesamtrelation R, die den Ausgangspunkt bildet,

13:03.590 --> 13:06.510
wieder rekonstruieren können durch Verbindungsoperationen.

13:06.970 --> 13:11.470
Und was dann an der Stelle gilt, ist, dass wir das verlustfrei und

13:11.470 --> 13:16.070
abhängigkeitsbewahrend immer dann tun können, wenn der Schlüssel einer

13:16.070 --> 13:20.150
Relation irgendwo in einer zweiten Relation noch als Attribut

13:20.150 --> 13:20.690
vorkommt.

13:21.430 --> 13:24.170
Das ist also, wie wir hier sehen, deshalb garantiert, weil wir in

13:24.170 --> 13:28.450
jedem Fall ja über die FDs Schlüsselbedingungen einführen.

13:30.090 --> 13:34.870
Aber es gibt immer noch Attribute, die beispielsweise an gar keiner FD

13:34.870 --> 13:38.570
beteiligt waren und die infolgedessen bisher nicht berücksichtigt

13:38.570 --> 13:39.190
worden sind.

13:39.850 --> 13:43.170
Also müssen wir in einem Schlussschritt auch noch alle die Attribute

13:43.170 --> 13:46.890
herausgreifen, die bisher nicht berücksichtigt worden sind, also

13:46.890 --> 13:47.690
keiner FD angehörten.

13:48.590 --> 13:52.270
Und man kann sich schnell überlegen, wenn das der Fall ist, wenn

13:52.270 --> 13:56.990
solche Attribute noch existieren, dann müssen die ja irgendwann mal in

13:56.990 --> 13:59.950
unserem Hüllenoperator aufgetaucht sein, als es um die

13:59.950 --> 14:00.850
Schlüsselbedingungen geht.

14:01.070 --> 14:06.750
Die müssen also irgendwie ja in dieser Hülle der Attribute unseres

14:06.750 --> 14:11.830
Schlüssels müssen ja diese Attribute noch vorgekommen sein.

14:12.610 --> 14:16.690
Also kann man auch umgekehrt sagen, demnach muss ich am Ende, um diese

14:16.690 --> 14:21.970
Attribute noch zu erwischen, mir einfach den Schlüssel von meiner

14:21.970 --> 14:23.810
ursprünglichen Relation R beschaffen.

14:23.810 --> 14:27.010
Und infolgedessen haben wir also einen Schlussschritt, der besagt,

14:27.450 --> 14:31.610
nimm dir noch einen Schlüssel von R und füge den noch danach hinzu.

14:33.270 --> 14:43.250
Aber das muss nur getan werden, wenn wir bisher nicht diesen

14:43.250 --> 14:46.130
kompletten Schlüssel schon in einer Relation als Schlüssel

14:46.130 --> 14:46.990
untergebracht haben.

14:47.090 --> 14:48.930
Wenn das der Fall ist, dann haben wir ja alle Attribute erwischt.

14:48.930 --> 14:52.670
Also, dieser letzte, man könnte auch sagen, dieser letzte Schritt

14:52.670 --> 15:09.230
kommt nur dann, wenn noch Attribute außerhalb der FD sind.

15:10.310 --> 15:11.690
Das war ein bisschen zu schnell.

15:19.080 --> 15:20.940
Ja, das ist auch so trickreich in die Ecke da.

15:22.700 --> 15:26.580
So, also dieser letzte Schritt besagt einfach, wenn uns ein Attribut

15:26.580 --> 15:28.920
übrig geblieben ist, das nicht in der funktionalen Abhängigkeit

15:28.920 --> 15:32.560
aufgetaucht ist, dann muss es zwangsläufig aber im Schlüssel unserer

15:32.560 --> 15:34.380
ursprünglichen Relation R drin gesteckt haben.

15:34.700 --> 15:37.480
Also machen wir einen letzten Schritt und holen uns einen solchen

15:37.480 --> 15:38.320
Schlüssel heraus.

15:38.780 --> 15:41.660
Und jetzt ist ja durchaus denkbar, dass mehrere Schlüssel existieren

15:43.280 --> 15:45.560
für unsere ursprüngliche Relation R.

15:45.980 --> 15:48.540
Dann können wir irgendein beliebigen wählen.

15:48.540 --> 15:51.000
Man sieht also, der Algorithmus ist nicht mal richtig deterministisch,

15:51.080 --> 15:54.520
weil er am Ende eine freie Wahl zulässt.

15:58.080 --> 16:00.920
So, es gibt hier übrigens in der Tat auch aus mehreren Gründen nicht

16:00.920 --> 16:05.500
eindeutig, also einmal Auswahl des Schlüssels am Ende, aber auch die

16:05.500 --> 16:07.820
kanonische Überdeckung, die Sortierung ist ja nicht eindeutig.

16:08.360 --> 16:13.300
Über dort, wo Attribute in gleicher Zahl auftreten, ist ja die Ordnung

16:13.300 --> 16:14.160
zunächst mal beliebig.

16:14.960 --> 16:17.120
Und wir greifen halt willkürlich eine davon heraus.

16:18.980 --> 16:21.440
So, das Ganze sollte jetzt funktionieren.

16:22.400 --> 16:27.580
Wir kennen ja schon die Zerlegung unserer Relation Fluginfo.

16:29.160 --> 16:32.980
Und die hatte ja, wenn Sie sich erinnern, eben diese fünf funktionalen

16:32.980 --> 16:33.210
Abhängigkeiten.

16:35.020 --> 16:36.600
Und zwar in dieser kanonischen Überdeckung.

16:37.140 --> 16:39.260
Jetzt brauchen wir ja nur den Algorithmus anzuwenden.

16:39.440 --> 16:42.340
Der Algorithmus ist geordnet.

16:42.640 --> 16:46.260
Hier haben wir 1, 2, 3, 4, 5, 6, 7 Attribute.

16:47.200 --> 16:49.580
Hier haben wir 4 Attribute im Spiel.

16:49.720 --> 16:51.500
Hier sind auch 4 Attribute im Spiel.

16:51.880 --> 16:54.580
Hier sind es noch 3 und hier sind es noch 2.

16:54.840 --> 16:57.740
Also haben wir zunächst mal unsere kanonische Überdeckung geordnet,

16:57.820 --> 17:00.260
nach der Zahl der Attribute.

17:01.800 --> 17:02.560
So, jetzt fangen wir an.

17:02.600 --> 17:05.200
Jetzt fangen wir mit der ersten an, die mit den sieben Attributen und

17:05.200 --> 17:07.720
überführen die in eine eigene Relation.

17:09.460 --> 17:10.220
Das sehen wir also hier.

17:11.120 --> 17:14.200
Da kriegen wir also erstmal eine Relation, die ist uns schon bekannt.

17:14.200 --> 17:16.400
Die haben wir auch schon früher erzeugt, allerdings nicht

17:16.400 --> 17:19.380
systematisch, sondern wir haben halt gesagt, naja, ich zerlege mal.

17:20.620 --> 17:24.340
Jetzt sehen wir hier, also dieses Ergebnis fällt uns zunächst mal aus

17:24.340 --> 17:25.960
diesem Algorithmus automatisch heraus.

17:26.780 --> 17:28.240
Dann können wir die zweite nehmen.

17:32.280 --> 17:37.740
Und das heißt, wir haben diese hier genommen, diese kanonische

17:37.740 --> 17:41.320
Funktionalabhängigkeit und haben hier Flugnummer, Ticketnummer,

17:41.420 --> 17:44.540
Platzdatum und Platzcode und Datum genommen.

17:45.120 --> 17:48.140
Und wir nehmen diese hier und Sie sehen, an dieser Stelle erzeugen wir

17:48.140 --> 17:53.300
keine neue Relation, sondern wir erzeugen nochmal die gleiche Relation

17:53.300 --> 17:55.960
und sehen daraus, dass es auf jeden Fall diese Buchung zwei Schlüssel

17:55.960 --> 17:56.220
hat.

17:57.080 --> 17:59.900
Nämlich auf der einen Seite Flugnummer und Ticketnummer und auf der

17:59.900 --> 18:02.360
anderen Seite Flugnummer, Platzcode und Datum.

18:02.360 --> 18:10.420
Das heißt, wir schlagen erstmal beide als FDs dieser Relation hinzu.

18:10.500 --> 18:12.580
Die hat also zwei FDs, wie wir sehen.

18:13.460 --> 18:17.500
Und stellt sich heraus, dass beide linken Seiten auch den Schlüssel

18:17.500 --> 18:20.740
definieren, weil sie jeweils dann insgesamt die Hülle über diese vier

18:20.740 --> 18:22.160
Attribute bilden.

18:23.520 --> 18:26.340
Oder genau, die vier Attribute in der Hülle enthalten.

18:27.940 --> 18:30.000
Gut, dann kommen wir zum nächsten Schritt.

18:30.000 --> 18:31.680
Jetzt haben wir die zwei blauen da erledigt.

18:31.780 --> 18:33.760
Der nächste ist jetzt von Nah und Entfernung.

18:34.280 --> 18:37.320
Da gibt es auch eine Relation, die uns schon bekannt ist, nämlich die

18:37.320 --> 18:38.380
Flugstrecke.

18:38.740 --> 18:42.080
Auch die, hier haben wir übrigens dann eine FD und hier haben wir auch

18:42.080 --> 18:44.620
eine FD in Sigma stehen.

18:45.460 --> 18:51.400
Und schließlich gibt es noch eine weitere hier, nämlich diese FD und

18:51.400 --> 18:54.620
die führt noch auf eine vierte Relation Ticket.

18:55.520 --> 19:00.820
Und jetzt sehen Sie, wir haben in der Tat das, was wir zuvor etwas

19:00.820 --> 19:05.480
rein gefühlsmäßig zunächst einmal durch Zerlegung erhalten, das

19:05.480 --> 19:07.220
erhalten wir ganz systematisch durch Zerlegung.

19:08.940 --> 19:12.680
Und da so ein schöner Algorithmus existiert, übrigens den letzten

19:12.680 --> 19:13.940
Schritt brauchen wir nicht mehr zu tun.

19:15.140 --> 19:20.120
Der letzte Schritt nämlich, wir haben bei Fluginfo, wenn Sie sich

19:20.120 --> 19:23.920
erinnern, Flugnummer und Ticketnummer als Attribut gehabt und

19:23.920 --> 19:31.380
Flugnummer, Platzcode und Datum als Schlüssel.

19:32.040 --> 19:34.780
Infolgedessen fällt der letzte Schritt weg.

19:36.840 --> 19:41.840
Also es kommt kein letzter Schritt mehr vor, indem wir noch den

19:41.840 --> 19:46.280
Schlüssel herausgreifen müssen von Fluginfo, weil der bereits erfasst

19:46.280 --> 19:49.580
worden ist in einer der anderen Relationen.

19:49.580 --> 19:53.640
Es gibt also kein Attribut, das außerhalb, das in keiner FTE

19:53.640 --> 19:56.500
vorgekommen wäre und das infolgedessen noch zusätzlich durch einen

19:56.500 --> 19:57.820
Schlüssel zu berücksichtigen wäre.

19:59.160 --> 20:00.300
Also sind wir fertig.

20:00.620 --> 20:03.780
Vier Relationen, das was wir früher gefühlsmäßig gemacht haben, das

20:03.780 --> 20:06.900
erreichen wir jetzt hier durch Anwendung dieses Algorithmus.

20:08.100 --> 20:12.500
Und die dritte Normalform, die nach außen nicht unbedingt zwingend

20:12.500 --> 20:15.580
ist, müssen wir bedenken, Benutzer außen haben Anwendungsprogramme

20:15.580 --> 20:17.920
laufen und brauchen ganz bestimmte Attribute gemeinsam.

20:18.560 --> 20:22.080
Die sind nicht unbedingt versessen darauf, dass ihnen eine dritte

20:22.080 --> 20:25.640
Normalform angeboten wird, sondern die wollen mit den Relationen

20:25.640 --> 20:28.860
umgehen, die ihnen rein von der Anwendung her eine vernünftige

20:28.860 --> 20:30.180
Zusammenfassung darstellen.

20:30.880 --> 20:34.480
Aber nach innen zu können wir so eine Zerlegung vornehmen, um zunächst

20:34.480 --> 20:38.920
mal sicherzustellen, dass wir keine Redundanzen erzeugen.

20:40.380 --> 20:44.000
Und beispielsweise kann man Benutzer ja auch vorschreiben, dass sie

20:44.000 --> 20:46.380
keine Änderungen vornehmen, sondern dass die Änderungen den

20:46.380 --> 20:49.740
Datenbankadministratoren überlassen bleiben und die würden zum

20:49.740 --> 20:52.360
Beispiel diese zerlegten Relationen vor sich sehen.

20:52.480 --> 20:55.760
Also es ist nicht so, dass wir bei der Zerlegung unbedingt allen die

20:55.760 --> 20:58.280
Zerlegung zu zeigen haben, sondern wir können bestimmten

20:58.280 --> 21:03.080
Benutzerkreisen unsere ursprüngliche Relation R weiterhin überlassen.

21:03.640 --> 21:07.380
Andere bekommen die zerlegten Relationen zu sehen, insbesondere die,

21:07.460 --> 21:10.660
die Änderungen verursachen und einspielen müssen.

21:11.360 --> 21:13.640
Und wie wir vielleicht noch ein bisschen uns ansehen werden in der

21:13.640 --> 21:18.480
nächsten Woche, ich kann nach innen zu sogar wieder die Zerlegung

21:18.480 --> 21:19.380
rückgängig machen.

21:20.600 --> 21:23.560
Da wird die Redundanz nach außen überhaupt nicht mehr sichtbar, aber

21:23.560 --> 21:26.280
aus Performancegründen kann sich zum Beispiel herausstellen, also Data

21:26.280 --> 21:29.520
Staging kann so sein, dass ich wieder die ursprüngliche Relation R

21:29.520 --> 21:31.040
intern handhaben will.

21:32.680 --> 21:35.480
Da sieht man also wie viele Optimierungsmöglichkeiten uns auch im

21:35.480 --> 21:38.420
Grunde genommen überlassen bleiben.

21:41.500 --> 21:44.920
So, die 4NF-Zerlegung, da gibt es auch eine Regel, die besagt

21:44.920 --> 21:49.660
folgendermaßen, nehmen wir mal an, wir hätten also hier eine MVD und

21:49.660 --> 21:55.260
leider ist X kein Superschlüssel, das heißt mit anderen Worten, wir

21:55.260 --> 21:57.500
haben zunächst mal noch nicht die vierte Normalform erreicht.

21:57.920 --> 22:00.780
Und wir stellen uns vor, dass wir die vierte Normalform erreichen

22:00.780 --> 22:04.000
wollen, denn, ich erinnere nochmal dran, solange wir die vierte

22:04.000 --> 22:08.000
Normalform nicht erreicht haben und eine MVD vorliegen haben, werden

22:08.000 --> 22:09.540
wir hochgradig redundant.

22:10.640 --> 22:15.000
Redundanz wollen wir beseitigen und wenn nun nur MVDs drin stecken und

22:15.000 --> 22:18.020
gar keine FDs, dann sind wir wahrscheinlich durch die dritte, nie

22:18.020 --> 22:20.900
haben wir bei der dritten Normalform eine Zerlegung vorgenommen.

22:21.020 --> 22:23.860
Wir sind immer noch bei der alten Relation, weil die die dritte

22:23.860 --> 22:27.300
Normalform erfüllt, weil wir MVDs noch nicht betrachtet haben.

22:27.400 --> 22:30.260
Also müssen wir doch einen Schritt weiter gehen und versuchen die

22:30.260 --> 22:35.180
Redundanzen zu entfernen und eine Relation, die zunächst einmal noch

22:35.180 --> 22:37.980
nicht in vierter Normalform ist, in vierter Normalform zu überführen.

22:38.540 --> 22:47.280
Jetzt wissen wir Folgendes, wenn wir eine mehrwertige Abhängigkeit X

22:47.280 --> 22:51.640
nach Y haben, dann gibt es ja auch eine mehrwertige Abhängigkeit X

22:51.640 --> 22:52.140
nach Z.

22:52.360 --> 22:58.140
Also X und Y sind unabhängig von der Belegung von Z und X, Z sind

22:58.140 --> 23:00.060
unabhängig von der Belegung von Y.

23:00.060 --> 23:02.540
Also die beiden haben nichts miteinander zu tun.

23:02.800 --> 23:05.380
Das hat man ja schon mal durch eine Aktion festgelegt.

23:05.940 --> 23:09.980
Also kann ich Folgendes sagen, wenn Folgendes gilt, die

23:09.980 --> 23:12.640
unterschiedlich sind, wenn das nicht unterschiedlich ist, dann gibt es

23:12.640 --> 23:20.840
sogenannte Entartete oder MVDs, dann zerlege ich einfach so, dass X

23:20.840 --> 23:23.820
und Y und X und Z eigene Relationen bilden.

23:27.440 --> 23:32.700
Und da wir weiterhin gesagt haben, diese Zerlegung hat ja mit X

23:32.700 --> 23:38.500
jeweils eine gemeinsame Attributmenge, können wir also auch

23:38.500 --> 23:43.400
nachweisen, dass wir durch die natürliche Verbindung dieser beiden

23:43.400 --> 23:46.400
Relationen wieder die ursprüngliche Relation herstellen können.

23:46.880 --> 23:50.540
Man kann also beweisen, dass diese Zerlegung verlustlos ist.

23:50.540 --> 23:55.720
Und das ist durchaus denkbar, dass zum Beispiel das X nach Y eine MVD

23:55.720 --> 23:59.340
und das X nach Z eine Funktion, eine FD ist.

24:00.600 --> 24:03.140
Auch dann würden wir eine solche Zerlegung vornehmen müssen.

24:06.510 --> 24:09.910
Wenn man das sehr früh macht, man könnte ja auch sagen, ich beginne

24:09.910 --> 24:13.310
sehr früh, als erstes nehme ich mir meine Fluginfo vor, da haben wir

24:13.310 --> 24:17.210
auch festgestellt, dass wir zwei MVDs drin haben und zerlege erstmal

24:17.210 --> 24:19.110
gemäß dieser MVDs.

24:20.210 --> 24:25.490
Dann könnte ich zum Beispiel anschließend das R1 und das R2 jeweils

24:25.490 --> 24:28.790
noch weiter bearbeiten, zum Beispiel jetzt unseren Algorithmus für die

24:28.790 --> 24:33.570
3NF durchschicken, um dann anschließend noch eine Zerlegung zu

24:33.570 --> 24:35.370
erhalten, die jetzt noch mit den FDs umgeht.

24:35.490 --> 24:38.510
Also ich habe dann mit den MVDs angefangen und habe dann anschließend

24:38.510 --> 24:40.310
mit den FDs weitergearbeitet.

24:40.990 --> 24:45.990
Also zwei Möglichkeiten, ich schaue mir erst die FDs an, zerlege in

24:45.990 --> 24:49.430
die dritte Normalform, schaue mir dann die resultierenden Relationen

24:49.430 --> 24:55.430
an und prüfe, ob dort noch MVDs vorkommen und wenn ja, dann muss ich

24:55.430 --> 24:57.810
anschließend noch eine weitere Zerlegung vornehmen, die dann

24:57.810 --> 25:00.230
allerdings eben nicht mehr abhängigkeitsbewahrend zwingend

25:00.230 --> 25:01.890
abhängigkeitsbewahrend ist.

25:02.070 --> 25:05.710
Andere Variante, ich fange erst mit den MVDs an, zerlege irgendein

25:05.710 --> 25:09.930
Ungetüm in etwas Kleineres und dann schicke ich diese kleineren

25:09.930 --> 25:14.070
Relationen, die beiden entstehenden, jeweils durch meinen Algorithmus

25:14.070 --> 25:17.810
durch und erzeuge dann schließlich, garantiere dann noch, dass diese

25:17.810 --> 25:23.110
drei, dass diese Zeilrelationen, die zerlegt werden in Relationen, die

25:23.110 --> 25:24.630
in dritter Normalform sind.

25:25.610 --> 25:28.330
Zwei Möglichkeiten, welche nehmen wir jetzt?

25:29.430 --> 25:30.250
Welche würden Sie denn nehmen?

25:31.650 --> 25:35.710
Fangen Sie mit den MVDs an und wenden dann die FDs an oder fangen Sie

25:35.710 --> 25:37.730
mit den FDs an und wenden dann die MVDs an.

25:37.730 --> 25:38.790
Was würden Sie machen?

25:41.390 --> 25:42.130
Irgendeine Vorstellung?

25:42.230 --> 25:42.930
Was würden Sie denn machen?

25:45.310 --> 25:46.970
Das sind immer so ekelhafte Entscheidungen.

25:47.470 --> 25:50.650
Ich sage Ihnen, was man alles machen kann und anschließend heißt,

25:50.770 --> 25:52.370
jetzt müssen Sie aber entscheiden, wie Sie es machen wollen.

25:52.770 --> 25:53.670
Was würden Sie machen?

25:55.610 --> 25:57.150
Erste MVDs oder erste FDs?

26:00.870 --> 26:04.590
Sehr unsicher, hat irgendjemand eine Vorstellung, ob er erste FDs

26:04.590 --> 26:05.710
nimmt oder erste MVDs?

26:07.190 --> 26:07.910
Und warum?

26:12.900 --> 26:18.240
Richtig, wir wissen, dass wenn wir mit den MVDs anfangen, dann eine

26:18.240 --> 26:20.900
Zerlegung vornehmen, von der wir keine Abhängigkeitsbewahrung

26:20.900 --> 26:21.560
garantieren können.

26:21.660 --> 26:23.840
Wir können nur die Verlustlosigkeit garantieren.

26:24.440 --> 26:28.540
Also wäre auch meine Idee, man legt erstmal den FDs los, geht in

26:28.540 --> 26:31.260
dritte Normalform, dann habe ich die Garantien und dann muss ich halt

26:31.260 --> 26:34.380
lokal, dann wird nämlich lokal nur noch bearbeitet, also irgendwo

26:34.380 --> 26:36.800
lokal kann es mir tatsächlich passieren, dass ich nicht mehr

26:36.800 --> 26:38.120
abhängigkeitsbewahrend bin.

26:38.740 --> 26:41.480
Wenn ich aber mit den MVDs anfange, dann fange ich in großem Stil

26:41.480 --> 26:45.640
gleich an, die Abhängigkeitsbewahrung infrage zu stellen und da muss

26:45.640 --> 26:48.600
ich also sehr viel sorgfältiger nachprüfen, ob ich tatsächlich

26:48.600 --> 26:52.700
trotzdem oder wo ich dann noch Konsistenzbedingungen anfügen muss.

26:53.460 --> 26:57.080
Also auch mein Vorschlag ist, obwohl das manchmal zunächst mal

26:57.080 --> 27:00.760
leichter erscheint, die MVDs zu nehmen, fangen Sie mit den FDs an,

27:00.920 --> 27:03.840
erzeugen Sie dritte Normalformen, prüfen Sie dann die entstehenden

27:03.840 --> 27:10.600
Teilrelationen, ob dort noch MVDs vorkommen, das ist also denkbar und

27:10.600 --> 27:14.240
versuchen Sie dann halt zu zerlegen und müssen halt dann feststellen,

27:14.420 --> 27:17.200
dass die Abhängigkeitsbewahrung nicht zwingend gesichert ist.

27:17.660 --> 27:21.120
Zu ernst ist das Problem allgemein aber nicht, denn wenn Sie sich

27:21.120 --> 27:23.740
wirklich Ihre ganzen Abhängigkeiten anschreiben, dann müssen Sie ja

27:23.740 --> 27:26.500
nur sehen, durchtrennen, bleibt noch irgendeine übrig, die durchtrennt

27:26.500 --> 27:27.840
wird bei der Zerlegung.

27:33.120 --> 27:37.340
Es gibt noch etwas weiteres und darauf bauen dann gleich noch eine

27:37.340 --> 27:41.720
weitere Menge von Normalformen, es gibt noch eine fünfte, sechste

27:41.720 --> 27:44.920
Normalform auf, die hängen zum Beispiel von den

27:44.920 --> 27:46.580
Inklusionsabhängigkeiten ab.

27:47.020 --> 27:50.600
Wir haben ja rein lokal gearbeitet, aber was wir sehen ist natürlich

27:50.600 --> 27:54.700
folgendes, durch die Zerlegung und durch den Zwang, dass wir am Ende

27:54.700 --> 27:59.020
wieder zusammenfügen müssen bei einer Verbindungsoperation, schleppen

27:59.020 --> 28:02.100
wir ja jetzt plötzlich so etwas wie zum Beispiel

28:02.100 --> 28:04.700
Fremdschlüsselbedingungen ein.

28:05.260 --> 28:07.760
Die Zerlegung war ja, schauen wir es uns gerade nochmal an, das können

28:07.760 --> 28:09.380
wir hier deutlich sehen an unserem Beispiel,

28:12.540 --> 28:16.700
hier sehen wir ja folgendes, unser Schlüssel ist, das sehen wir aus

28:16.700 --> 28:20.640
der obersten der funktionalen Abhängigkeit, Flugnummer.

28:23.040 --> 28:28.580
So jetzt muss natürlich, damit wir Flug irgendwie wieder einbringen

28:28.580 --> 28:31.740
können, um dann die ursprüngliche Relation zu konstruieren, muss

28:31.740 --> 28:34.720
natürlich Flugnummer irgendwo anders vorkommen, als beispielsweise

28:34.720 --> 28:35.260
Fremdschlüssel.

28:35.660 --> 28:39.560
Und wir sehen auch schon in der Tat, er taucht hier wieder auf, in der

28:39.560 --> 28:40.280
zweiten Relation.

28:42.780 --> 28:46.780
Infolgedessen ist also in der zweiten Relation Buchung Flugnummer ein

28:46.780 --> 28:51.100
Fremdschlüssel, der sich bezieht auf den Schlüssel von Flug.

28:52.120 --> 28:55.140
Wir können mal weiter gehen, wir sehen, dass in der zweiten Relation

28:55.140 --> 29:01.740
ja zwei Schlüssel vorkommen, nämlich Flug- und Ticketnummer und

29:01.740 --> 29:07.620
außerdem auch noch sehr viel komplizierter Flugnummer, Platzcode und

29:07.620 --> 29:08.040
Datum.

29:10.910 --> 29:16.570
Nun ist die Frage, ob da möglicherweise von diesen Attributen auch ein

29:16.570 --> 29:17.370
Fremdschlüssel ist.

29:17.450 --> 29:19.950
Gehen wir mal zur letzten Relation über, dann haben wir nämlich Ticket

29:19.950 --> 29:22.990
und da sehen wir, dass Ticketnummer Schlüssel ist.

29:23.150 --> 29:26.630
Also haben wir an dieser Stelle Flugnummer und Ticketnummer bereits

29:26.630 --> 29:27.170
erledigt.

29:29.790 --> 29:35.450
Jetzt kommt noch als letztes die Relation von und nach.

29:35.450 --> 29:39.730
Da ist der Schlüssel von und nach, aber wir können gleich mal

29:39.730 --> 29:42.750
nachsehen, ob der irgendwo anders vorkommt.

29:42.930 --> 29:44.790
Und in der Tat, er kommt bei Flug vor.

29:46.690 --> 29:49.490
Das heißt, wir haben jetzt an dieser Stelle Folgendes erreicht,

29:50.650 --> 29:57.930
Buchung selbst hat keinen Schlüssel, der als Fremdschlüssel irgendwo

29:57.930 --> 29:58.570
anders vorkommt.

29:58.730 --> 30:00.870
Es sind immer nur Komponenten, die woanders vorkommen.

30:00.870 --> 30:07.650
Aber von allen anderen drei Relationen kommt der Schlüssel jeweils in

30:07.650 --> 30:10.390
einer der anderen Relationen als Fremdschlüssel vor.

30:11.210 --> 30:17.190
Flugstrecke in Flug, Ticket in Buchung.

30:18.030 --> 30:21.990
Und man kann jetzt also nachweisen, dass dann, wenn immer paarweise

30:21.990 --> 30:27.890
solche Fremdschlüsselbeziehungen existieren, dass dann in der Tat das

30:27.890 --> 30:33.530
Ergebnis der Verbindungsoperation verlustlos ist.

30:35.370 --> 30:38.010
Und jetzt kann man sich vielleicht sogar noch überlegen, wie kommt das

30:38.010 --> 30:42.130
eigentlich, dass Buchung da so einen Spezialkarakter hat, dass bei

30:42.130 --> 30:45.670
Buchung einfach nur Fremdschlüssel vorkommen, dass aber der Schlüssel

30:45.670 --> 30:49.030
von Buchung in keiner der anderen drei Relationen vorkommt.

30:49.430 --> 30:50.830
Woran kann denn das liegen eigentlich?

30:51.530 --> 30:55.970
Man kann ja auch mal so reingehen und sich so Relationen analysieren

30:55.970 --> 30:58.870
und dann sagen, da gibt es bestimmte Eigenschaften, die fallen mir

30:58.870 --> 30:59.290
auf.

30:59.750 --> 31:02.110
Kann man die auf irgendein anderes Phänomen zurückführen?

31:02.470 --> 31:02.670
Wieso?

31:03.250 --> 31:04.250
Können wir mal die Frage stellen?

31:09.640 --> 31:15.080
Ja, da bin ich nicht ganz sicher, ob man das so sehen kann.

31:16.640 --> 31:18.620
Wir sind eigentlich sehr mechanisch vorgegangen.

31:18.620 --> 31:23.540
Wir wussten nur, dass die Buchung auch ein Teil aus einer MVD

31:23.540 --> 31:24.500
hervorgehen könnte.

31:25.100 --> 31:27.100
Das ist vielleicht schon ein klein bisschen Hinweis, dass

31:27.100 --> 31:30.480
infolgedessen keine Fremdschlüsselbedingungen auftauchen könnten.

31:30.600 --> 31:31.900
Aber gibt es noch eine andere Ursache?

31:32.460 --> 31:34.460
Können wir sich noch eine andere vorstellen, warum Buchung diese

31:34.460 --> 31:35.540
besondere Eigenschaft hat?

31:40.800 --> 31:45.120
Mit ein bisschen Erfahrung sieht man es schon.

31:45.480 --> 31:49.020
Und zwar, jetzt müssen wir zurückgehen zu UML, zu ihrer ursprünglichen

31:49.020 --> 31:49.520
Analyse.

31:49.520 --> 31:52.340
Und da war Buchung eine Beziehung.

31:52.760 --> 31:57.460
Man kann also eigentlich rückwärts schließen und sagen, immer dann,

31:57.660 --> 32:02.140
wenn ich eine Relation habe, die einen relativ komplizierten Schlüssel

32:02.140 --> 32:04.540
hat, also einen, der aus mehreren Attributen besteht, und diese

32:04.540 --> 32:08.280
Attribute sind ihrerseits, diese Komponenten sind Fremdschlüssel an

32:08.280 --> 32:13.400
einer anderen Stelle, dann handelt es sich offensichtlich, wenn wir

32:13.400 --> 32:17.640
rückwärts gehen nach UML, um die Darstellung einer Assoziation oder

32:17.640 --> 32:19.740
die Repräsentation einer Assoziation.

32:22.040 --> 32:28.620
Und dass wir hier, dass nicht der gesamte Schlüssel auftaucht, das

32:28.620 --> 32:32.840
hängt jetzt damit zusammen, dass wir hier noch Datum oder Platzcode

32:32.840 --> 32:34.800
haben, und wenn Sie sich erinnern, das waren so Attribute.

32:36.900 --> 32:40.220
Diese Rückwärtsüberlegung zurück in UML ist gar nicht uninteressant.

32:40.220 --> 32:43.860
Und zwar, sie spielt dann eine Rolle, stellen Sie sich mal Folgendes

32:43.860 --> 32:48.040
vor, Sie haben jetzt dieses Datenbasis-Schema, Datenbasis aufgebaut,

32:48.460 --> 32:52.520
nach fünf Jahren stellt man fest, dass das nicht so richtig mehr mit

32:52.520 --> 32:56.000
den augenblicklichen Verhältnissen übereinstimmt und Sie müssen Ihr

32:56.000 --> 32:57.240
Schema irgendwie revidieren.

32:58.860 --> 33:02.420
Jetzt sind alle, die jemals mit dem Entwurf zu tun hatten, sind schon

33:02.420 --> 33:05.180
lange nicht mehr da, sie sind auf sich allein gestellt und müssen

33:05.180 --> 33:07.060
rauskriegen, was sie sich damals gedacht haben.

33:07.060 --> 33:10.140
Und dann dummerweise ist auch die Dokumentation höchst lückenhaft,

33:10.300 --> 33:13.240
niemand kann so richtig mehr vollziehen, was damals das ursprüngliche

33:13.240 --> 33:14.180
UML -Schema war.

33:14.760 --> 33:17.800
Und dann macht man sich dran und versucht, das ursprüngliche UML

33:17.800 --> 33:19.040
-Schema zu rekonstruieren.

33:20.220 --> 33:23.540
Deshalb gibt es also umgekehrt nämlich auch, nicht nur das, was ich

33:23.540 --> 33:26.740
Ihnen vorgeführt habe, ich habe ein UML-Schema und jetzt versuche ich

33:26.740 --> 33:29.360
es in Relationen zu überführen, sondern gelegentlich gibt es eine

33:29.360 --> 33:33.480
umgekehrte Notwendigkeit, ich muss versuchen, wieder ein UML-Schema zu

33:33.480 --> 33:37.960
rekonstruieren, an dem dann meine Änderungen der MiniWelt irgendwie

33:37.960 --> 33:40.700
unterzubringen und dann wieder zurück zu transformieren in das

33:40.700 --> 33:41.500
relationale Schema.

33:41.600 --> 33:43.020
Und da muss ich anschließend auch noch überlegen, wie ich die

33:43.020 --> 33:45.780
Datenbasis nun anpasse, damit es dem neuen Schema gehorcht.

33:46.660 --> 33:49.680
Und da stellt man dann solche Überlegungen wie die, die ich gerade

33:49.680 --> 33:52.740
angestellt habe, an, dass man nämlich sagt, Buchung hat da irgendeinen

33:52.740 --> 33:55.720
Spezialkarakter, das ist wohl eine Assoziation.

33:56.980 --> 34:00.020
Wobei man dann auch feststellt, dass es nicht mal ganz einfach ist,

34:00.720 --> 34:04.040
eindeutig eine Rückabbildung in Assoziation vorzuleben, sondern man

34:04.040 --> 34:06.980
hat auch möglicherweise mehrere Möglichkeiten, das zu tun.

34:09.200 --> 34:12.980
So, und die Inklusionsabhängigkeiten, die sind jetzt, das ist

34:12.980 --> 34:16.820
sozusagen jetzt wiederum formal erfasst, an welchen Stellen jetzt

34:16.820 --> 34:19.540
diese Fremdschlüsselbedingungen eintreten.

34:20.820 --> 34:24.320
Und die kann man also auch noch mit formal unterbringen und man kann

34:24.320 --> 34:26.940
auch über diese Inklusionsabhängigkeiten noch zusätzliche Aussagen

34:26.940 --> 34:31.700
machen, insbesondere kann man auch noch bestimmte weitere Normalformen

34:31.700 --> 34:34.740
dann einführen, die dann etwas darüber aussagen, wie z.B.

34:34.920 --> 34:37.940
welche zusätzlichen Bedingungen man noch an die Joint-Operationen

34:37.940 --> 34:38.200
stellt.

34:40.100 --> 34:43.140
So, Inklusionsabhängigkeit sagt aber nichts anderes, als dass ich im

34:43.140 --> 34:50.820
Wesentlichen dann verlange, dass bei der Projektion jeweils die eine

34:50.820 --> 34:52.360
Projektion eine Teilmenge der anderen ist.

34:53.440 --> 34:57.160
So, damit wären wir durch mit dem Datenbankentwurf.

34:57.160 --> 35:00.500
Und Sie sehen also, dass der...

35:00.500 --> 35:02.020
Ach, doch, das müsste hier gehen.

35:02.680 --> 35:03.900
Ah, wunderbar, funktioniert.

35:06.540 --> 35:08.160
Wenn wir jetzt hier auch noch draufdrücken...

35:08.980 --> 35:11.120
Nein, dann habe ich jetzt aber Mist gemacht.

35:11.360 --> 35:12.320
Jetzt müssen wir nochmal zurück.

35:14.720 --> 35:18.420
Jetzt müsste ich doch...

35:18.420 --> 35:19.980
Ja, okay.

35:24.900 --> 35:27.180
So, ich erinnere also nochmal, wir haben einmal so diese

35:27.180 --> 35:32.400
makroskopische Sicht angelegt beim Datenbankentwurf und dann diese

35:32.400 --> 35:36.720
mikroskopische Sicht, die einfach versucht nachzuarbeiten und die im

35:36.720 --> 35:39.000
Wesentlichen darauf zielt, relationale Datenbanken herzustellen.

35:40.120 --> 35:42.300
Und ich hatte gesagt, weshalb ich mich so lange mit dem

35:42.300 --> 35:46.400
Datenbankentwurf beschäftigt habe, hat damit zu tun, dass wir am

35:46.400 --> 35:50.880
Schluss immer Geschäftsprozesse außen in der realen Welt bedienen

35:50.880 --> 35:53.420
müssen, dass wir die verstehen müssen und dass wir deren

35:53.420 --> 35:57.160
Informationsbedürfnisse abbilden müssen in die Datenbanken.

35:57.160 --> 36:00.540
Ich hatte ja gesagt, ich gehe sehr viel weiter nach außen in Richtung

36:00.540 --> 36:05.280
der Anwendungen als Frau Zitterbart, aber unter der Hand muss ich

36:05.280 --> 36:07.180
immer sagen, ich verlasse mich immer völlig darauf, dass die

36:07.180 --> 36:13.260
Telematiker mir eine so ordentliche Übertragungstechnik bieten, auf

36:13.260 --> 36:16.480
der die zuverlässig ist und robust ist, sodass ich mich rein um die

36:16.480 --> 36:21.040
Datenbankprobleme beschäftige, auf die ich mich konzentrieren kann.

36:21.140 --> 36:23.880
Aber ich werde in der letzten Woche dann den Sprung machen und sagen,

36:23.940 --> 36:25.500
jetzt müssen wir die beiden doch wieder zusammenbringen.

36:25.500 --> 36:28.560
Aber zuvor steht noch was anderes bevor, nämlich die

36:28.560 --> 36:29.460
Transaktionsverwaltung.

36:30.860 --> 36:34.900
Die hat jetzt mit der Robustheit zu tun.

36:36.720 --> 36:40.580
Und wir haben sie ja eingeführt, weil wir gesagt haben, wir müssen

36:40.580 --> 36:42.670
Transaktionsprozeduren einführen.

36:43.400 --> 36:46.980
Für die gilt nämlich dann folgendes, erstmal jede Operation, die

36:46.980 --> 36:49.880
überhaupt stattfindet, wird in eine Transaktion eingebettet.

36:49.880 --> 36:55.100
Das heißt, Dienstfunktionen sind immer Transaktionen und das war

36:55.100 --> 36:59.480
deshalb, weil jede Transaktion für sich die Konsistenz gewährleistet.

36:59.980 --> 37:02.260
Und dann hatten wir gesagt, naja, und dann werden wir das auch gleich

37:02.260 --> 37:04.580
noch für die Robustheit heranziehen.

37:06.500 --> 37:10.180
Wir müssen halt noch gewisse Garantien abgeben, was die Transaktionen

37:10.180 --> 37:13.600
angeht und die Garantien sind im Wesentlichen, dass wir eine

37:13.600 --> 37:16.820
erfolgreiche Transaktion garantiert uns, dass wir einen Zustand

37:16.820 --> 37:20.900
erreichen, den wir Persistentenzustand nannten und der dann in einen

37:20.900 --> 37:24.280
dauerhaften Zustand überführt werden kann, dass er dann auch dauerhaft

37:24.280 --> 37:24.580
bleibt.

37:24.680 --> 37:28.560
Und wir haben gesagt, muss die Archivverwaltung dafür Sorge tragen.

37:29.240 --> 37:32.320
Und das andere war, wenn es schief geht, dann müssen wir in der Lage

37:32.320 --> 37:35.080
sein, irgendeinen konsistenten Zustand anzusteuern, von dem wir aus

37:35.080 --> 37:36.100
wieder weiterarbeiten können.

37:37.060 --> 37:38.900
Das wollen wir jetzt etwas präziser machen.

37:41.080 --> 37:44.240
Und das ist auch keine so einfache Aufgabe.

37:44.560 --> 37:47.160
Wir werden sogar relativ einfache Transaktionen nur betrachten.

37:47.400 --> 37:50.120
Aber wir werden mal durchgehen und dann zeigen, was wir eigentlich zu

37:50.120 --> 37:50.800
beachten haben.

37:50.900 --> 37:54.040
Und zwar zunächst mal nur von den Eigenschaften nach außen und noch

37:54.040 --> 37:58.360
gar nicht von der Implementierung her, um diese Robustheit und

37:58.360 --> 38:00.340
Konsistenzwahrung tatsächlich durchzusetzen.

38:01.100 --> 38:02.900
Also wir wissen, die Transaktionsprozedur...

38:03.560 --> 38:04.760
Achso, jetzt geht das schon wieder los.

38:12.760 --> 38:18.440
Transaktionsprozedur, das ist einfach eine Klammerung um eine Folge

38:18.440 --> 38:22.320
von Operationen, von denen wir sagen, innerhalb der Transaktion kann

38:22.320 --> 38:26.140
der Zustand nicht inkonsistent sein, aber wenn wir am Ende sind, dann

38:26.140 --> 38:27.380
muss er konsistent sein.

38:27.480 --> 38:30.860
Und am Anfang muss er auch konsistent gewesen sein, denn die

38:30.860 --> 38:33.460
Transaktion gibt natürlich nur die Garantie ab, wenn sie auf einen

38:33.460 --> 38:35.900
konsistenten Zustand stößt, dann liefert sie auch wieder einen

38:35.900 --> 38:37.060
konsistenten Zustand ab.

38:37.060 --> 38:39.740
So, wenn wir eine Transaktion ausführen, und das kann ja beliebig

38:39.740 --> 38:44.140
häufig sein, dann sprechen wir von einer Transaktion, insbesondere

38:44.140 --> 38:48.220
unsere modernen Transaktionssysteme haben so tausend oder sowas

38:48.220 --> 38:52.020
vorgefertigte Transaktionen auf Lager und ich gehe nur über Masken

38:52.020 --> 38:58.260
rein und versehe dann die Transaktion mit Parameter, rufe dann halt

38:58.260 --> 39:00.280
über die Maske eine Transaktion auf.

39:02.160 --> 39:05.420
Übrigens, warum spricht man eigentlich von Transaktionssystemen und

39:05.420 --> 39:09.400
meint also Systeme mit vorgefertigten Transaktionen und Masken, über

39:09.400 --> 39:10.180
die man herankommt?

39:11.980 --> 39:13.240
Warum macht man eigentlich sowas?

39:14.000 --> 39:14.700
Irgendeine Vorstellung?

39:15.580 --> 39:19.440
Platz buchen ist ganz typisch heute in Transaktionssystemen, alles was

39:19.440 --> 39:25.240
über Bankaktionen, das wäre über Transaktionssysteme abgewickelt.

39:25.240 --> 39:28.520
Wenn Sie zum Beispiel an einen Bankautomaten gehen, dann werden hinten

39:28.520 --> 39:30.240
einfach Transaktionen ab.

39:31.380 --> 39:35.740
Warum kommen Sie eigentlich nur über vorgefertigte Transaktionen an so

39:35.740 --> 39:36.400
ein System ran?

39:38.460 --> 39:39.240
Irgendeine Vorstellung?

39:41.120 --> 39:43.320
Wobei so eine bestimmte Auswahl zwischen Tausenden haben.

39:46.640 --> 39:48.880
Die Transaktion ist ja was ganz Kritisches.

39:50.440 --> 39:52.140
Nämlich, die gibt uns ja Garantien ab.

39:52.880 --> 39:55.840
Konsistenzgarantien und Robustheitsgarantien.

39:56.640 --> 39:59.900
Wir können uns gar nicht leisten, dass irgendjemand für sich einfach

39:59.900 --> 40:02.880
mal so eine Transaktion definiert und dann steckt das in ein System

40:02.880 --> 40:08.520
rein, völlig ungeprüft und dann stellt sich hinterher heraus, dass sie

40:08.520 --> 40:10.160
gar nicht konsistenzwahrend ist.

40:10.280 --> 40:12.980
Denn wenn Sie eine Transaktion mal drin laufen haben, die nicht

40:12.980 --> 40:17.040
konsistenzwahrend ist und Ihre Datenbasis ist dann anschließend nicht

40:17.040 --> 40:20.240
mehr konsistent, dann gilt sofort wieder die Regel, eine Transaktion

40:20.240 --> 40:24.100
führt in einen konsistenten Zustand über.

40:24.340 --> 40:26.520
Aber es ist nichts darüber ausgesagt, was die Transaktion macht, wenn

40:26.520 --> 40:28.560
sie auf einen inkonsistenten Zustand stößt.

40:28.780 --> 40:31.860
Also die Gefahr, dass Transaktionen, wenn sie auf einen inkonsistenten

40:31.860 --> 40:35.800
Zustand stoßen, nur noch inkonsistente Zustände hinterlassen, die ist

40:35.800 --> 40:37.080
außerordentlich groß.

40:37.840 --> 40:41.480
Also werden wir überhaupt nie in Transaktionssysteme irgendwelche

40:41.480 --> 40:45.920
Transaktionen einspielen, die nicht vorher auf Herz und Nieren geprüft

40:45.920 --> 40:46.200
sind.

40:47.140 --> 40:50.220
Und solche Systeme sind also eigentlich nach außen hin abgekapselt.

40:50.320 --> 40:52.260
Sie können nur Transaktionen ausführen, aber sie können keine

40:52.260 --> 40:52.760
definieren.

40:53.060 --> 40:56.780
Das ist einfach den Spezialisten vorbehalten, die sie dann auch zur

40:56.780 --> 40:58.480
Verantwortung ziehen können, wenn was schief geht.

41:00.020 --> 41:02.340
So und dann brauchen wir natürlich, weil jetzt wissen wir ja, dass die

41:02.340 --> 41:03.900
Transaktionen überlappend ablaufen.

41:04.120 --> 41:07.360
Nicht jedermann startet zu irgendeinem beliebigen Zeitpunkt

41:07.360 --> 41:08.120
Transaktionen.

41:08.520 --> 41:10.820
Die Wahrscheinlichkeit, dass gerade schon ein Haufen Transaktionen im

41:10.820 --> 41:12.220
System laufen, ist sehr hoch.

41:12.220 --> 41:15.960
Also brauchen wir eine Transaktionsverwaltung, die nichts anderes

41:15.960 --> 41:21.360
macht, als eine Menge von Transaktionen zu steuern in ihrem Ablauf.

41:21.460 --> 41:25.580
Im einfachsten Fall überlappen sie nicht und im Normalfall überlappen

41:25.580 --> 41:25.960
die halt.

41:26.720 --> 41:30.580
Was wir uns ansehen müssen, ist natürlich was passiert, wenn die sich

41:30.580 --> 41:31.140
überlappen.

41:31.140 --> 41:34.460
Und da erinnere ich noch dran, wir hatten schon mal gesagt, was

41:34.460 --> 41:41.100
passieren kann, ist, dass an dieser Stelle sich sowas wie ein Konflikt

41:41.100 --> 41:45.680
einstellt, bei dem nämlich versuchen mehrere Transaktionen mit den

41:45.680 --> 41:46.840
gleichen Daten zu arbeiten.

41:47.280 --> 41:50.560
Zwei Reisebüros versuchen halt unglücklicherweise gerade auf dem

41:50.560 --> 41:51.840
selben Flugzeug zu buchen.

41:52.840 --> 41:59.300
Und da ist ja das bekannte Beispiel, es ist noch ein Platz da und sie

41:59.300 --> 42:02.420
müssen sicherstellen, dass der Platz nicht an beide Interessenten

42:02.420 --> 42:04.140
vergeben wird, sondern nur an einen.

42:05.160 --> 42:08.880
Sie müssen nicht garantieren, dass es ein ganz bestimmter der beiden

42:08.880 --> 42:12.060
Bewerber erhält, aber sie müssen sichergehen, dass auf jeden Fall nur

42:12.060 --> 42:15.080
einer der beiden Kandidaten noch diesen Sitzplatz erhält.

42:15.080 --> 42:19.700
Wenn sie da irgendeinen Fehler machen, wenn sie den Konflikt nicht

42:19.700 --> 42:22.640
sauber lösen, dann stellen sie sich zum Beispiel am Gate hinterher

42:22.640 --> 42:25.360
fest, dass plötzlich zwei mit der gleichen Platznummer erscheinen.

42:26.460 --> 42:28.800
Dann kann man auch mit Geld arbeiten, um den einen davon zu

42:28.800 --> 42:30.420
überzeugen, doch lieber zurückzutreten.

42:32.380 --> 42:35.720
Aber ich kenne auch schon Situationen, es passiert mir zwar nicht

42:35.720 --> 42:41.660
sowas, aber trotzdem, dadurch, dass bewusst überbucht wird, gibt es

42:41.660 --> 42:44.000
schon manchmal recht nette Situationen, wenn keiner zurücktreten will.

42:47.370 --> 42:49.970
So jetzt müssen wir mal ansehen, wer ist eigentlich überhaupt für was

42:49.970 --> 42:50.710
verantwortlich.

42:52.310 --> 42:56.730
Wir haben ja gesagt, die Transaktion ist eine Einheit der Konsistenz.

42:57.470 --> 43:01.630
Und deshalb geben wir der Transaktion zunächst einmal eine Eigenschaft

43:01.630 --> 43:05.610
mit, nämlich wir sagen, sie ist konsistent.

43:06.490 --> 43:08.450
Auf Englisch heißt das Consistency.

43:09.410 --> 43:13.550
Und nochmal, eine Transaktion, wenn sie einen konsistenten Zustand

43:13.550 --> 43:17.430
antrifft, dann bewirkt sie auch einen konsistenten Zustandsübergang,

43:17.550 --> 43:20.890
das heißt der Endzustand ist auch wieder konsistent.

43:21.650 --> 43:26.270
Und die Transaktionsverwaltung kann das nicht garantieren, sondern das

43:26.270 --> 43:29.250
ist die Forderung, die sie an die Transaktion stellt.

43:30.190 --> 43:31.990
Das ist die einzige Forderung, die sie wirklich stellt.

43:32.330 --> 43:35.330
Sie stellt nur eine einzige Forderung und sagt, dieser konsistente

43:35.330 --> 43:38.770
Zustandsübergang muss von dir Transaktion gewährleistet werden.

43:38.770 --> 43:42.890
Deshalb eben, wie gesagt, erst auf Herz und Nieren zu prüfen, bevor

43:42.890 --> 43:47.590
man sie einspielt, weil diese Garantie, weil sich das System selbst,

43:47.830 --> 43:51.070
die Transaktionsverwaltung, genau auf diese Garantie verlässt.

43:51.410 --> 43:54.630
Das ist also eine Forderung, die die Transaktionsverwaltung an die

43:54.630 --> 43:55.710
Transaktion stellt.

43:57.350 --> 44:01.470
Und die Transaktionsverwaltung sagt, nur wenn diese Bedingung erfüllt

44:01.470 --> 44:02.710
ist, garantiere ich den Rest.

44:03.890 --> 44:08.530
Nämlich die übliche Robustheit und die Konsistenz auch für die gesamte

44:08.530 --> 44:09.590
Menge der Transaktionen.

44:11.110 --> 44:15.250
Und weil die Verantwortlichkeit bei der Transaktion entsteht, deshalb

44:15.250 --> 44:18.370
sagen wir, das ist einfach die lokale Konsistenz der Transaktionen.

44:18.890 --> 44:22.310
Also Ausgangspunkt ist die lokale Konsistenz der Transaktionen, die

44:22.310 --> 44:23.130
müssen wir garantieren.

44:24.130 --> 44:27.650
So, jetzt alle weiteren Garantien übernimmt dann unsere

44:27.650 --> 44:28.590
Transaktionsverwaltung.

44:28.970 --> 44:33.910
Insbesondere übernimmt sie zunächst einmal folgende eigene Garantie,

44:34.530 --> 44:36.150
die sogenannte Atomicität.

44:37.890 --> 44:40.890
Wir wissen ja folgendes, wenn die Transaktion erfolgreich zum Ende

44:40.890 --> 44:44.370
kommt, dann gilt das Ergebnis der Transaktion.

44:44.370 --> 44:46.530
Und wenn sie es nicht schafft bis zum Ende zu kommen, aus welchen

44:46.530 --> 44:52.990
Gründen auch immer, dann müssen wir einen Zustand anstreben, von dem

44:52.990 --> 44:54.470
wir wissen, dass er konsistent ist.

44:57.150 --> 45:00.910
Jetzt nehmen wir mal die Fälle an, dass die Transaktion relativ kurz

45:00.910 --> 45:01.330
läuft.

45:02.570 --> 45:05.070
Dass sie also nicht allzu viele Operationen ausführt, auch nicht allzu

45:05.070 --> 45:07.470
viele Daten anfasst.

45:07.470 --> 45:11.270
Dann kann man sagen, das Einfachste, was wir tun können an dieser

45:11.270 --> 45:15.270
Stelle, mit relativ wenig Schaden, den wir anrichten, ist, dass wir

45:15.270 --> 45:17.410
einfach wieder an den Anfang der Transaktion zurückspringen.

45:17.510 --> 45:20.030
Das heißt, wir tun so, als ob die Transaktion nie gelaufen wäre.

45:22.410 --> 45:26.910
Und wir nennen dann eine solche Situation die Atomicität der

45:26.910 --> 45:27.490
Transaktion.

45:27.490 --> 45:32.370
Sie kommt entweder vollständig zum Ende, hinterlässt dann tatsächlich

45:32.370 --> 45:35.390
den Endzustand, der wird persistent gemacht.

45:35.690 --> 45:37.910
Oder sie kommt nicht dahin, dann springt sie wieder zurück und tut so,

45:37.970 --> 45:39.050
als ob sie nie gelaufen wäre.

45:39.370 --> 45:42.470
Das heißt, es wird wieder der Zustand hergestellt, wie die Transaktion

45:42.470 --> 45:44.170
ihn zu Anfang gefunden hat.

45:44.790 --> 45:47.050
Und zu Anfang gefunden heißt natürlich, ich muss nur wissen, was hat

45:47.050 --> 45:49.430
die eigentlich angefasst zwischendrin, denn ich muss nur diesen

45:49.430 --> 45:53.070
lokalen Ausschnitt, den die Transaktion wirklich bearbeitet hat,

45:53.110 --> 45:54.710
wieder in seinen alten Zustand versetzen.

45:54.710 --> 45:56.650
Der Rest kann natürlich unverändert bleiben.

45:58.070 --> 46:01.590
Also, entweder ist sie transient, zwar so lange, bis wir zum Ende

46:01.590 --> 46:02.110
gekommen sind.

46:02.230 --> 46:05.610
Im Augenblick, in dem wir zum Ende gekommen sind, ist sie persistent.

46:08.350 --> 46:14.530
Da wir im Augenblick von der lokalen Konsistenz sprechen, heißt das

46:14.530 --> 46:20.850
natürlich auch, dass sich Transienz und Persistenz auf die von der

46:20.850 --> 46:22.630
Transaktion betroffenen Zustände beziehen.

46:23.430 --> 46:26.250
Da die Transaktion nichts weiß über das, was wir sonst an der

46:26.250 --> 46:30.670
Transaktion gemacht haben, können wir also auch die Atomicität,

46:30.810 --> 46:35.410
nämlich den Endzustand, den Anfangszustand, nur bezüglich des Teils

46:35.410 --> 46:41.570
betrachten, den die Transaktion wirklich auch selbst gesehen hat und

46:41.570 --> 46:42.350
angefasst hat.

46:42.850 --> 46:45.010
Das werden wir dann sehen, wenn wir ein Modell entwickeln, dann müssen

46:45.010 --> 46:48.230
wir also irgendwie kennzeichnen all die Elemente, die die Transaktion

46:48.230 --> 46:49.630
selbst angefasst hat.

46:52.250 --> 46:58.310
Aber, weil Störungen nur selten von den Transaktionen selbst

46:58.310 --> 46:58.810
herrühren.

46:59.230 --> 47:02.670
Zum Beispiel eine Transaktion, bei der der Benutzer sagt, ich will

47:02.670 --> 47:05.170
nicht mehr weitermachen, aus der Buchung wird nichts mehr.

47:05.930 --> 47:09.110
Da kann man sagen, die liegt in der Verantwortung der Transaktion und

47:09.110 --> 47:13.250
die sagt meistens auch dann selbst ab Bord, das heißt springt zurück.

47:14.010 --> 47:18.870
Aber viele Störungen, zum Beispiel Systembricht zusammen oder was wir

47:18.870 --> 47:22.050
noch sehen werden, Transaktionen können sich auch verklemmen und ich

47:22.050 --> 47:27.230
muss irgendeine da zurücksetzen oder auch, dass irgendwo durch Null

47:27.230 --> 47:29.930
dividiert wird oder sonst irgendein Fehler auftritt, der wird ja

47:29.930 --> 47:31.570
außerhalb der Transaktion beobachtet.

47:31.570 --> 47:34.450
Die kann möglicherweise überhaupt nicht mehr eingreifen, häufig kennt

47:34.450 --> 47:36.130
sie überhaupt nicht die Situation und den Fehler.

47:37.510 --> 47:41.130
Infolgedessen werden wir einfach alles, was mit Atomicität zu tun hat,

47:41.350 --> 47:44.770
werden wir dem Recovery-Verwalter übertragen, von dem wir ja wissen,

47:45.110 --> 47:47.710
dass wir in der Segment-Verwaltung untergebracht haben, also im

47:47.710 --> 47:50.670
Wesentlichen dann irgendwie mit Seiten zu tun hat.

47:53.130 --> 47:55.250
Nächste Aufgabe ist die Dauerhaftigkeit.

47:56.390 --> 48:01.750
Die Dauerhaftigkeit, hatten wir ja gesagt, das ist, wenn wir die

48:01.750 --> 48:10.230
Persistenz erreicht haben, dann muss irgendwie dann hinterher

48:10.230 --> 48:13.950
sichergestellt werden, dass wie auch immer die Störungen aussehen,

48:13.950 --> 48:18.630
dann, dass wir in jedem Fall die Effekt, die Wirkung dieser

48:18.630 --> 48:22.690
Transaktion nicht mehr verlieren, es sei denn, wir kommen in der

48:22.690 --> 48:25.510
zweiten Transaktion und die macht dann die ursprüngliche Wirkung

48:25.510 --> 48:26.190
wieder hinfällig.

48:26.290 --> 48:31.570
Zum Beispiel, wenn noch drei Plätze frei sind, dann wird zunächst

48:31.570 --> 48:34.730
einmal dauerhaft gemacht, die Tatsache, dass wir einen dieser Plätze

48:34.730 --> 48:37.510
belegt haben, aber natürlich kann hinterher ein Storno kommen aus

48:37.510 --> 48:39.850
einer weiteren Transaktion und diesen Zustand wieder aufheben.

48:43.080 --> 48:48.400
Wenn aber einmal die Transaktion gelaufen ist, dann kann die schon

48:48.400 --> 48:50.700
wieder auch nicht mehr die Verantwortung übernehmen für die

48:50.700 --> 48:51.420
Dauerhaftigkeit.

48:52.520 --> 48:55.440
Aber auch die Transaktionsverwaltung kann das nicht tun, denn die

48:55.440 --> 48:57.560
Transaktionsverwaltung, irgendwann fahren wir das System mal runter,

48:57.700 --> 49:01.040
dann ist die Transaktionsverwaltung erstmal zerweckt und wenn die

49:01.040 --> 49:03.360
wieder hochgefahren wird, dann haben wir eine neue Instanzierung der

49:03.360 --> 49:04.480
Transaktionsverwaltung.

49:04.480 --> 49:08.300
Die Lebensdauer aber unserer Daten reicht ja über dieses runterfahren

49:08.300 --> 49:09.340
und hochfahren hinaus.

49:09.800 --> 49:13.320
Also müssen wir auch da eine eigene Komponente schaffen und die hat

49:13.320 --> 49:15.820
man ja als Archivverwaltung betrachtet.

49:16.100 --> 49:21.740
Aber was wir sehen werden, was wir tun müssen ist, wir müssen die mit

49:21.740 --> 49:27.720
der Atomicität, die muss die Dauerhaftigkeit mit berücksichtigen.

49:27.720 --> 49:32.380
Die muss also Maßnahmen ergreifen, sodass nicht dann, wenn schon alles

49:32.380 --> 49:39.260
irgendwie verschwunden ist, dass das System runtergefahren ist, dass

49:39.260 --> 49:41.320
dann plötzlich noch Daten verloren gehen können.

49:42.080 --> 49:44.120
Jetzt würden Sie mir sagen, das ist doch ganz einfach, am Ende der

49:44.120 --> 49:46.300
Transaktion schreibe ich alles auf den Hintergrundspeicher raus.

49:47.060 --> 49:49.460
Aber das stellt sich heraus, aus Performancegründen würde man es

49:49.460 --> 49:50.520
häufig gar nicht tun können.

49:50.520 --> 49:53.580
Das heißt zunächst mal sitzen eigentlich die Daten noch sehr

49:53.580 --> 49:55.740
verwundbar in unserem System drin.

49:56.160 --> 49:59.340
Unsere Transaktion ist fertig, die Transaktionsverwaltung hakt das

49:59.340 --> 50:01.940
irgendwann mal ab und jetzt müssen wir sicherstellen, dass trotzdem

50:01.940 --> 50:04.620
dieser Zustand nicht mehr verloren gehen kann.

50:05.520 --> 50:08.980
Das müssen wir also doch, da müssen wir noch gewisse Maßnahmen in der

50:08.980 --> 50:10.520
Transaktionsverwaltung selbst vorsehen.

50:12.740 --> 50:15.840
Und dann haben wir noch unsere Konflikte zu betrachten.

50:15.980 --> 50:18.520
Bis jetzt haben wir jede Transaktion einzeln für sich betrachtet.

50:18.700 --> 50:20.800
Ein Fehler, der auftritt, trifft zunächst mal die einzelne

50:20.800 --> 50:21.540
Transaktion.

50:21.640 --> 50:25.880
Er trifft möglicherweise mehrere Transaktionen gemeinsam, aber

50:25.880 --> 50:29.240
trotzdem, jede Transaktion ist erstmal auf sich selbst gestellt.

50:30.660 --> 50:34.400
In dem Augenblick, in dem Konflikte auftreten, verhaken sich ja

50:34.400 --> 50:36.060
plötzlich mehrere Transaktionen miteinander.

50:36.060 --> 50:39.840
Es wird das gleiche Datum angefasst und wir müssen jetzt plötzlich

50:39.840 --> 50:42.220
mehrere Transaktionen gemeinsam betrachten.

50:42.760 --> 50:47.420
Und wir wissen ja schon, das kennen Sie ja auch aus der

50:47.420 --> 50:52.180
Betriebssystemtechnik oder Systemorganisation, dass ja durchaus, wenn

50:52.180 --> 50:56.700
zum Beispiel zwei Prozesse die gleichen Daten verwenden, dass wir

50:56.700 --> 51:00.160
irgendwelche Maßnahmen ergreifen müssen, sodass zu jedem Zeitpunkt nur

51:00.160 --> 51:02.800
einer der Prozesse an dieses Datum herankommt.

51:02.800 --> 51:05.100
So etwas jeniges müssen wir ja auch machen, wenn wir das nicht tun,

51:05.180 --> 51:06.480
dann kommt es zu Wechselwirkungen.

51:06.920 --> 51:10.300
Und was schlimmer noch ist, diese Wechselwirkungen haben zur Folge,

51:10.400 --> 51:12.740
dass die Datenbank nicht mehr konsistent ist.

51:12.900 --> 51:15.600
Oder zumindest die Gefahr besteht, dass sie nicht mehr konsistent ist.

51:16.340 --> 51:20.000
Es reicht also nicht aus, nur lokal die Konsistenz sicherzustellen,

51:20.100 --> 51:22.560
das macht die Transaktion, sondern es muss auch noch jemand

51:22.560 --> 51:25.660
Verantwortung dafür übernehmen, dass wenn jetzt zu Wechselwirkungen

51:25.660 --> 51:28.220
kommt, dass trotzdem die Konsistenz gewahrt bleibt.

51:28.220 --> 51:33.200
Und wir nennen den Teil, der jetzt durch das Zusammenwirken mehrerer

51:33.200 --> 51:36.920
Transaktionen bedingt ist und durch die Konflikte, die da zunächst mal

51:36.920 --> 51:41.640
drohen, dass wir globale Konsistenz durchsetzen wollen.

51:41.760 --> 51:43.920
Also nicht nur lokale, das ist die Voraussetzung, aber wir wollen

51:43.920 --> 51:45.340
global die Konsistenz durchsetzen.

51:46.680 --> 51:50.020
Und da erinnert sich auch, da hatten wir schon mal einen ganz

51:50.020 --> 51:52.060
einfachen Grundsatz, wir haben nämlich gesagt, machen wir das doch

51:52.060 --> 51:57.100
folgendermaßen, nehmen wir als ein Kriterium daher, dass eine

51:57.100 --> 52:04.640
Transaktion nur dann korrekt funktionieren kann, wenn sie so abläuft,

52:04.740 --> 52:06.300
als ob sie ganz allein im System wäre.

52:06.780 --> 52:09.540
Das ist nur durch die lokale Konsistenz ihre Aufgabe.

52:10.060 --> 52:15.040
Wenn wir also sicherstellen können, dass jede Transaktion so abläuft,

52:15.220 --> 52:17.680
als ob es die anderen gar nicht gäbe, selbst wenn sie sich richtig

52:17.680 --> 52:22.460
streiten an bestimmten Stellen und zu Konflikten führen, dann soll die

52:22.460 --> 52:26.100
einzelne Transaktion den Konflikt überhaupt nicht zu sehen kriegen und

52:26.100 --> 52:30.500
stattdessen sie das Gefühl haben, sie läuft ganz alleine ab und die

52:30.500 --> 52:33.740
einzige Verantwortung, die sie übernimmt, ist die lokale Konsistenz

52:33.740 --> 52:34.580
und die reicht auch aus.

52:35.080 --> 52:38.100
Mit der lokalen Konsistenz ist die globale Konsistenz gewährleistet.

52:38.940 --> 52:42.220
Dazu führt man eine Eigenschaft ein, die sogenannte Isolation.

52:43.280 --> 52:46.400
Das heißt nichts anderes, als man isoliert die Transaktionen so

52:46.400 --> 52:49.600
voneinander, dass sie tatsächlich so ablaufen, als ob sie ganz alleine

52:49.600 --> 52:49.960
wären.

52:51.580 --> 52:58.020
Es gibt also keine schädliche Vermischung von Zustandsübergängen.

52:59.640 --> 53:02.640
Man kann also sagen, die gleichlaufenden Transaktionen laufen

53:02.640 --> 53:03.800
sozusagen außer Konkurrenz.

53:03.860 --> 53:05.440
Es gibt gar keine Konkurrenz aus deren Sicht.

53:06.860 --> 53:09.140
Und jetzt müssen wir wieder sagen, wer übernimmt die Verantwortung?

53:10.060 --> 53:14.200
Das ist nicht der gleiche Teil, der sich den Möbelns Recovery

53:14.200 --> 53:17.180
bezeichnet, der jetzt mit dieser Atomicität zu tun hat und Persistenz

53:17.180 --> 53:21.020
oder Transizenz sichern muss, sondern dazu brauchen wir eine eigene

53:21.020 --> 53:24.060
Komponente, den Scheduler, der einfach dafür Sorge trägt, dass nun

53:24.060 --> 53:28.240
tatsächlich diese Isolationseigenschaft erreicht wird und nicht eine

53:28.240 --> 53:30.340
primitive Isolationseigenschaft ist die folgende.

53:31.340 --> 53:34.660
Ich lasse eine Transaktion loslaufen und die kommt irgendwo hin und

53:34.660 --> 53:37.480
will auf ein Datum zugreifen und das hat bereits eine andere

53:37.480 --> 53:40.140
Transaktion in Beschlag genommen, die noch läuft.

53:41.220 --> 53:43.600
Dann ist das Einfachste mittlerweile, ich halte meine eigene

53:43.600 --> 53:46.280
Transaktion an, die muss halt warten bis die andere Transaktion fertig

53:46.280 --> 53:48.260
ist und wenn die dann fertig ist, dann kann ich weitermachen.

53:49.400 --> 53:52.300
Das wäre ein ganz einfaches Verfahren für eine Isolation.

53:53.040 --> 53:56.920
Es gibt noch ein einfaches Verfahren, meine Transaktion kommt an und

53:56.920 --> 53:59.220
ich stelle gerade fest, da läuft schon eine andere Transaktion, dann

53:59.220 --> 54:02.820
bleibt meine gleich mal hängen und darf überhaupt erst loslaufen, wenn

54:02.820 --> 54:04.600
die andere Transaktion abgeschlossen ist.

54:04.600 --> 54:07.140
Jetzt stellen Sie sich mal für 10.000 Transaktionen vor, die da so

54:07.140 --> 54:10.440
alle gleichmäßig ankommen und dann können Sie sich vorstellen, dass

54:10.440 --> 54:12.260
unser System nahezu gar nicht mehr reagiert.

54:13.360 --> 54:16.720
Also etwas schlauer müssen wir sein, aber wir wollen in jedem Fall

54:16.720 --> 54:19.500
sicherstellen, dass wir die Transaktionen irgendwie so ablaufen

54:19.500 --> 54:22.700
lassen, dass sie sich gegenseitig nicht beeinflussen, also isoliert

54:22.700 --> 54:25.140
voneinander ablaufen und wir nennen das ein Scheduler.

54:28.460 --> 54:30.860
So, jetzt können wir diese Eigenschaften mal schön hintereinander

54:30.860 --> 54:37.800
schreiben, nämlich die Atomicität, die Konsistenz, lokal und global,

54:38.320 --> 54:46.020
Consistency, Isolation und Dauerhaftigkeit, und es gibt dann, wenn man

54:46.020 --> 54:48.500
es rundeinander schreibt, die schöne Abkürzung ACID.

54:49.900 --> 54:53.340
Und wenn Sie sich also nach außen hin als ein Kenner der

54:53.340 --> 54:57.060
Transaktionsverwaltung ausgeben wollen, dann lassen Sie einfach in

54:57.060 --> 55:00.320
regelmäßigen Abständen das Wort ACID fallen, dann sind Sie also als

55:00.320 --> 55:03.480
Kenner der Materie bereits identifiziert.

55:04.900 --> 55:08.040
Und wir werden also wirklich nichts anderes tun, als uns mit diesen

55:08.040 --> 55:09.740
vier Eigenschaften jetzt halt rumschlagen.

55:13.790 --> 55:17.130
Jetzt muss man sagen, ich hatte ja so eine Voraussetzung gemacht, und

55:17.130 --> 55:20.430
zwar die Voraussetzung war eben, wir können es tatsächlich leisten,

55:20.470 --> 55:22.890
wieder am Anfang der Transaktion zurückzuspringen, wenn irgendwas

55:22.890 --> 55:25.130
schief geht, weil die kurz läuft.

55:25.950 --> 55:29.910
Also kein großer Schaden, wenig Daten werden angefasst, es läuft auch

55:29.910 --> 55:30.610
nicht sonderlich lang.

55:30.610 --> 55:34.650
Und deshalb können wir also einfach wieder am Anfang zurückspringen.

55:35.790 --> 55:39.670
Und das ist also zum Beispiel bei Buchungen sehr wohl der Fall.

55:40.030 --> 55:45.850
Man spricht übrigens auch hier gerne von Debit Credit Transaktionen.

55:47.370 --> 55:54.230
Das ist so der Typ der Transaktionen, oder der Repräsentant der

55:54.230 --> 55:57.590
Transaktionen, die diese ACID Eigenschaften ohne weiteres aufweisen

55:57.590 --> 55:57.930
können.

55:58.790 --> 56:02.450
Es gibt natürlich auch andere Transaktionen, bei denen ist das nicht

56:02.450 --> 56:03.150
ganz so schön.

56:03.870 --> 56:09.490
Zum Beispiel gibt es da die Situation der kooperativen Anwendungen.

56:09.850 --> 56:13.530
Also zwei Entwerfer sitzen da und entwerfen meinetwegen jetzt gerade

56:13.530 --> 56:15.790
vom Airbus 380 den Flügel.

56:16.550 --> 56:19.470
Und das ist eine ordentliche Aufgabe, da muss man mit CAD-Werkzeugen

56:19.470 --> 56:23.190
arbeiten, hat eigentlich ein ganzes Heer von Entwerfern, muss auch

56:23.190 --> 56:26.250
eine Menge simulieren, weil man heute ja nicht mehr alles in den

56:26.250 --> 56:27.130
Luftkanal steckt.

56:28.130 --> 56:31.010
Und jetzt ändert da irgendeiner an einer Stelle und das hat einen

56:31.010 --> 56:32.510
Effekt auf andere Entwerfer.

56:32.730 --> 56:36.030
Ist da bei der Krümmung irgendetwas angepasst, dann ist plötzlich der

56:36.030 --> 56:39.490
Luftstrom, verändert sich auf die Art, der simuliert, muss also auch

56:39.490 --> 56:40.450
erneut simulieren.

56:41.310 --> 56:43.670
Und wenn Sie sich jetzt vorstellen, dass das alles schön isoliert

56:43.670 --> 56:49.650
abläuft, dann muss immer einer seine Arbeit zu Ende machen, das kann

56:49.650 --> 56:53.350
aber sehr lange dauern, und dann kommt der Nächste ins Spiel, statt

56:53.350 --> 56:57.350
dass jemand dann parallel gleich die Simulation startet und sagt, nee,

56:57.410 --> 56:59.930
nee, das kannst du nicht so machen, da musst du wieder zurück und

56:59.930 --> 57:01.610
nochmal eine Änderung vornehmen.

57:01.870 --> 57:03.450
Also kooperatives Arbeiten.

57:05.250 --> 57:09.350
Welche unserer vier Eigenschaften ACID würden Sie denn fallen lassen

57:09.350 --> 57:11.370
in einer solchen Situation?

57:15.860 --> 57:19.240
Wenn Sie jetzt nämlich dabei bleiben bei ACID, dann ist natürlich

57:19.240 --> 57:21.240
keine Rede davon, dass Sie irgendwie kooperieren können.

57:23.160 --> 57:26.080
Jede Transaktion verhält sich ja so, als ob sie alleine wäre.

57:27.640 --> 57:32.200
Also es gibt gar keine Möglichkeit der Kooperation, außer man wartet,

57:32.420 --> 57:35.760
bis jemand fertig ist, und dann fängt man seine eigene Transaktion an.

57:36.380 --> 57:37.920
Also welche Eigenschaft würde man denn aufgeben?

57:39.940 --> 57:40.920
Isolation gehen wir auf.

57:41.380 --> 57:44.060
Denn Isolation sagt ja, die beiden wissen nichts voneinander, und

57:44.060 --> 57:45.300
jetzt sollen die ja was voneinander wissen.

57:46.200 --> 57:49.020
Also bei CAD gibt man im Allgemeinen die Isolation auf.

57:49.960 --> 57:54.080
Und jetzt gibt es eine Menge komplizierter Modelle, da entstehen

57:54.080 --> 57:59.360
sofort sehr komplizierte Transaktionsmodelle, die man zurückführt dann

57:59.360 --> 58:02.440
auf Basistransaktionen, die immer noch ACID sind.

58:03.120 --> 58:06.780
Man muss nämlich Zwischenergebnisse jetzt plötzlich sichtbar machen.

58:07.660 --> 58:08.760
Langlaufende Vorgänge.

58:10.640 --> 58:13.460
Das ist auch so eine Sache, also jetzt nehmen wir nochmal unsere

58:13.460 --> 58:16.720
Buchung, und Sie haben eine lange und eine Transaktion, da wird also

58:16.720 --> 58:22.740
gebucht, das Hotel, und der Flug, und das Mietauto, und meinetwegen

58:22.740 --> 58:25.340
noch der Besuch der Nationalparks, und weiß der Henker ja, wir haben

58:25.340 --> 58:29.080
eine riesen Liste, und Sie sagen, nur wenn das erfolgreich ist,

58:29.140 --> 58:30.020
entsteht die Buchung.

58:30.400 --> 58:33.520
Also eine halbe Stunde sitzen Sie in Ihrem Reisebüro, bis das endlich

58:33.520 --> 58:34.600
unter Dach und Fach ist.

58:35.100 --> 58:35.440
Mindestens.

58:36.620 --> 58:41.280
Wollen Sie jetzt alles andere anhalten, was auch zufällig gerade

58:41.280 --> 58:43.800
buchen will, und ähnliche Ereignisse buchen wollen?

58:44.640 --> 58:49.360
Oder wenn, dann sagen Sie zu allem Überfluss auch noch folgendes, wenn

58:49.360 --> 58:51.940
das mit dem Besuch nicht klappt, dann verschiebe ich überhaupt den

58:51.940 --> 58:53.620
Zeitpunkt, ich will eine Woche später reisen.

58:54.820 --> 58:57.900
Wollen Sie jetzt, oder ich will zumindest, oder wenn das mit dem

58:57.900 --> 59:00.700
Mietauto nicht klappt, dann werden Sie nicht unbedingt sagen, deshalb

59:00.700 --> 59:03.980
lasse ich jetzt die Hotelbuchung und das Flugzeug fallen, aber ich

59:03.980 --> 59:07.020
überlege mir vielleicht irgendeine Alternative, jetzt heuer ich mir

59:07.020 --> 59:08.800
einen Fahrer an, mit seinem Auto.

59:10.700 --> 59:16.660
Wollen Sie da wirklich eine ACID-Transaktion haben, oder was würden

59:16.660 --> 59:17.620
Sie denn da aufgeben?

59:24.480 --> 59:29.780
Lange laufend und wenn etwas schief geht, dann ist es schief gegangen,

59:30.000 --> 59:30.660
zurück an den Anfang.

59:31.900 --> 59:33.300
Würden Sie auch wahrscheinlich nicht machen.

59:33.600 --> 59:38.440
Dann würden Sie sagen, naja, dann nehmen wir ein Stück der Transaktion

59:38.440 --> 59:39.480
zurück, aber nicht alles.

59:40.320 --> 59:42.540
Also werden wir die Atomicität an der Hand haben.

59:44.600 --> 59:48.240
Also wir werden deshalb die Atomicität, da arbeiten wir auch mit

59:48.240 --> 59:50.880
sogenannten Sicherungspunkten, dann springt man nur ein Stück zurück,

59:51.080 --> 59:54.140
gibt auch spezifische Arten von Transaktionen, mit denen man umgehen

59:54.140 --> 59:54.400
kann.

59:54.920 --> 59:58.820
Und dann gibt es noch eine andere Technik, ein anderes statistisches

59:58.820 --> 59:59.760
Analyseverfahren.

01:00:02.760 --> 01:00:04.860
Da kann man auch etwas aufgeben, und zwar kann man die

01:00:04.860 --> 01:00:06.020
Konsistenzforderung aufgeben.

01:00:06.520 --> 01:00:09.440
Wenn Sie Statistik treiben, dann ist es nicht so kritisch, ob nun

01:00:09.440 --> 01:00:12.020
wirklich alles so konsistent ist, oder ob da so ein paar Fehler drin

01:00:12.020 --> 01:00:12.360
sind.

01:00:13.040 --> 01:00:16.460
Das bügelt sich im Allgemeinen bei hinreichend großer Zahl der

01:00:16.460 --> 01:00:17.920
Stichprobe, bügelt sich das aus.

01:00:18.880 --> 01:00:23.600
Und Sie werden dann lieber akzeptieren, dass die Daten nicht ganz

01:00:23.600 --> 01:00:27.320
korrekt sind, und solange Sie nur Statistik treiben, können Sie das

01:00:27.320 --> 01:00:29.140
eigentlich tolerieren.

01:00:29.940 --> 01:00:34.200
Und in all den Fällen erhöhen Sie halt den Grad, den Parallelitätsgrad

01:00:34.200 --> 01:00:35.280
an Transaktionen.

01:00:35.280 --> 01:00:37.940
Also Asset-Eigenschaften sind nicht immer gut.

01:00:38.940 --> 01:00:42.380
Und für all diese verschiedenen Situationen gibt es deswegen auch viel

01:00:42.380 --> 01:00:47.980
kompliziertere Modelle, von denen aber eine Aussage immer gilt, ganz

01:00:47.980 --> 01:00:51.540
unten, dann machen Sie zum Beispiel verschachtelte Transaktionen, aber

01:00:51.540 --> 01:00:55.060
das Basiselement sind immer noch Asset-Transaktionen.

01:00:55.400 --> 01:00:58.240
Also sollten wir auf jeden Fall Asset-Transaktionen verstehen, und

01:00:58.240 --> 01:01:01.240
jedes System, jedes Datenbanksystem, aber auch heute jede Mittelwehr,

01:01:01.660 --> 01:01:05.980
bietet auch zumindest teilweise die Asset-Eigenschaften an.

01:01:09.760 --> 01:01:13.300
So, jetzt sind wir also an der Stelle, dass wir sagen, wir werden in

01:01:13.300 --> 01:01:16.880
jedem Fall, weil das der Kern ist, Asset-Transaktionen behandeln.

01:01:18.520 --> 01:01:22.500
Nun ist ja die Forderung, dass wir Konsistenz erhalten, zu erarbeiten,

01:01:22.500 --> 01:01:27.200
also zum Beispiel Isolation wirklich durchsetzen, oder auch Recovery

01:01:27.200 --> 01:01:32.680
-Eigenschaften durchsetzen müssen, das ist ja eine extrem kritische

01:01:32.680 --> 01:01:33.480
Frage.

01:01:33.860 --> 01:01:36.240
Wir wollen ja Robustheitsgarantien abgeben.

01:01:36.340 --> 01:01:40.900
Sie gehen raus beispielsweise, und Sie sind eigener und

01:01:40.900 --> 01:01:43.800
selbstständiger Unternehmer, werfen so eine Transaktionsverwaltung auf

01:01:43.800 --> 01:01:46.400
den Markt und sagen, die schlägt alles an, was bisher auf dem Markt

01:01:46.400 --> 01:01:50.480
war, und dann entdecken Sie nach einiger Zeit, dass es ein

01:01:50.480 --> 01:01:52.040
Produkthaftungsgesetz gibt.

01:01:52.720 --> 01:01:54.880
Wenn irgendwas schief geht, dann haften Sie mit Ihrem Produkt.

01:01:56.300 --> 01:02:00.080
Und wenn Ihnen derjenige, bei dem der Schaden, weil Sie einen Fehler

01:02:00.080 --> 01:02:03.920
gemacht haben, bei dem Sie Schaden angerichtet haben, nachweist, dass

01:02:03.920 --> 01:02:06.340
er 10 Millionen Schaden dadurch erlangt hat, dann müssen Sie die 10

01:02:06.340 --> 01:02:07.520
Millionen von Ihnen wieder haben.

01:02:08.380 --> 01:02:11.120
Und wenn Sie am Anfang Ihres Unternehmens stehen, dann garantiert

01:02:11.120 --> 01:02:12.100
haben Sie keine 10 Millionen.

01:02:12.960 --> 01:02:16.840
Das heißt, Sie können sofort Insolvenz anmelden.

01:02:17.740 --> 01:02:22.580
Da werden Sie zwar die Schulden, die 10 Millionen, los, aber meistens

01:02:22.580 --> 01:02:24.980
werden Sie auch Ihr gesamtes Privatvermögen bei der Gelegenheit los.

01:02:27.480 --> 01:02:32.200
Also wäre es doch besser, wir hätten irgendwelche Mittel an der Hand,

01:02:32.440 --> 01:02:35.740
um uns selber erstmal zu überzeugen, dass das, was wir da rausgeben,

01:02:36.120 --> 01:02:40.900
dass das tatsächlich die Garantien, die ich auch per Vertrag ja

01:02:40.900 --> 01:02:43.480
eingehen muss, wenn ich so ein Produkt liefere, dass die erfüllt

01:02:43.480 --> 01:02:43.860
werden.

01:02:44.780 --> 01:02:48.060
Und bei der Transaktionsverwaltung und allen Robustheitsfragen stellt

01:02:48.060 --> 01:02:51.540
sich halt heraus, es ist gut, man geht das formal vor.

01:02:52.040 --> 01:02:55.560
Wir brauchen also ein formales Modell jetzt, anhand dessen wir so

01:02:55.560 --> 01:02:57.900
Transaktionen beschreiben können und dann gewisse Untersuchungen

01:02:57.900 --> 01:03:02.100
anstellen können, was die Garantien angeht, die wir abgeben wollen.

01:03:03.780 --> 01:03:07.540
Na ja, das ist die erste Frage, wie beschreiben wir denn so eine

01:03:07.540 --> 01:03:08.180
Transaktion?

01:03:10.420 --> 01:03:12.600
Wir machen etwas ganz Einfaches.

01:03:14.000 --> 01:03:16.880
Wir führen ein sogenanntes Leseschreibmodell ein.

01:03:18.040 --> 01:03:23.100
Das heißt, wir nehmen einfach den Standpunkt ein, wir gucken von

01:03:23.100 --> 01:03:25.540
außen, wir sind die Transaktionsverwaltung beispielsweise, wir

01:03:25.540 --> 01:03:27.120
schreiben uns die Transaktion von außen an.

01:03:28.140 --> 01:03:30.340
Und von der Transaktion haben wir ja gesagt, sie ist verantwortlich

01:03:30.340 --> 01:03:32.540
dafür, dass sie lokale Konsistenz sichert.

01:03:32.540 --> 01:03:37.180
Es gibt also gar keinen Grund, warum wir uns die Transaktion genau von

01:03:37.180 --> 01:03:41.560
innen ansehen, sondern es genügt, lediglich deren Effekte, die sie

01:03:41.560 --> 01:03:47.360
nach außen zeigt, zu beobachten und dann alle Maßnahmen auf diesen von

01:03:47.360 --> 01:03:49.480
außen beobachteten Effekten aufzubauen.

01:03:49.900 --> 01:03:51.420
Und von außen sehen wir Folgendes.

01:03:52.540 --> 01:03:58.160
Von außen sehen wir, dass eine Transaktion ein Commit gibt oder ein

01:03:58.160 --> 01:03:58.780
Abort gibt.

01:03:58.780 --> 01:04:01.580
Oder außerdem sagt, ich fange jetzt an.

01:04:03.480 --> 01:04:05.280
Und dann wissen wir noch etwas weiteres.

01:04:06.480 --> 01:04:12.800
Sie gibt eine Anweisung und sagt, lies mal irgendein Datenelement X

01:04:12.800 --> 01:04:18.780
oder sie sagt weiterhin, schreib mal ein Datenelement X.

01:04:20.040 --> 01:04:26.660
Und sie sagt im Übrigen, meine Daten, die führe ich in einen privaten

01:04:26.660 --> 01:04:28.800
Arbeitsspeicherbereich.

01:04:29.620 --> 01:04:36.340
Das heißt, wenn ich lese, dann heißt Read X, lese das X in diesen

01:04:36.340 --> 01:04:42.620
privaten Bereich ein und bei Write X sage ich, da steht in meinem

01:04:42.620 --> 01:04:46.940
privaten Arbeitsbereich etwas drin und schreibe das doch bitte aus und

01:04:46.940 --> 01:04:49.200
lesen und schreiben heißt immer auf den Hintergrund speichern.

01:04:52.160 --> 01:04:56.300
So, und das Datenelement ist, je nachdem, das lassen wir jetzt völlig

01:04:56.300 --> 01:04:57.220
offen, was das ist.

01:04:57.340 --> 01:04:58.540
Normalerweise ist das eine Seite.

01:05:00.120 --> 01:05:03.940
So, also unsere Transaktionsverwaltung sieht nur diese Operation.

01:05:04.460 --> 01:05:04.900
Das Einzige.

01:05:05.020 --> 01:05:08.920
Und jetzt muss sie ihr ganzes Verhalten auf diesen beobachtbaren vier

01:05:08.920 --> 01:05:10.100
Operationen aufbauen.

01:05:11.620 --> 01:05:15.100
Wir werden gleich noch sehen, wir machen doch noch etwas weiteres.

01:05:15.180 --> 01:05:19.660
Wir machen den Arbeitsbereich nicht ganz so privat, sodass die

01:05:19.660 --> 01:05:23.320
Transaktionsverwaltung zumindest mit einer Einrichtung kommunizieren

01:05:23.320 --> 01:05:28.220
kann, nämlich die Pufferverwaltung, um zu wissen, was ist denn der

01:05:28.220 --> 01:05:30.480
Status dieses Arbeitsbereiches.

01:05:33.360 --> 01:05:38.880
So, jetzt wollen wir also, insbesondere sagen wir also, dass diese

01:05:38.880 --> 01:05:44.560
Folge, die wir von außen beobachten können, dass diese Folge die

01:05:44.560 --> 01:05:46.960
lokale Konsistenz wart.

01:05:47.480 --> 01:05:49.440
Was immer die Transaktion sonst noch tut.

01:05:49.720 --> 01:05:54.320
Wir beobachten übrigens etwas nicht, was im Datenbankbereich auch

01:05:54.320 --> 01:05:57.000
unkritisch ist, aber sobald wir zum Beispiel in den Bereich der

01:05:57.000 --> 01:05:59.680
Mittelwähr gehen, sofort wieder etwas kritischer wird, nämlich wir

01:05:59.680 --> 01:06:01.900
sehen nicht, wie die Transaktion nach außen wirkt.

01:06:02.760 --> 01:06:07.420
Ob die jetzt zum Beispiel auch noch mit Ihnen am Rechner kommuniziert

01:06:07.420 --> 01:06:10.460
und Ihnen zwischendrin irgendwelche Ausgaben gibt.

01:06:10.540 --> 01:06:13.300
Nehmen wir an, die gibt Ihnen die Ausgabe, Sie haben den Sitz sowieso

01:06:13.300 --> 01:06:16.100
und dann bricht die Transaktion ab und wird zurückgesetzt.

01:06:16.740 --> 01:06:18.400
Dann kriegen Sie das möglicherweise gar nicht mehr mit.

01:06:18.780 --> 01:06:20.060
Sie haben noch die alte Ausgabe.

01:06:20.600 --> 01:06:21.840
Das prüfen wir nicht nach.

01:06:22.300 --> 01:06:26.420
Wenn die Transaktion also leichtsinnigerweise, ohne schon zum

01:06:26.420 --> 01:06:30.360
erfolgreichen Ende gekommen zu sein, Ausgaben produziert, dann ist das

01:06:30.360 --> 01:06:33.020
aus unserer Sicht der Datenverwaltung völlig gleichgültig.

01:06:33.620 --> 01:06:36.100
Das ist eine Sache, mit der muss der Benutzer fertig werden.

01:06:36.460 --> 01:06:38.420
Was geht mich der Benutzer an als Datenbanksystem?

01:06:40.100 --> 01:06:43.900
Und ich habe nur dafür Sorge zu tragen, dass die Datenbasis konsistent

01:06:43.900 --> 01:06:44.300
bleibt.

01:06:45.340 --> 01:06:49.880
Deshalb reicht uns also Read, Write, Commit und Abort aus, aber wie

01:06:49.880 --> 01:06:52.440
gesagt, das da erfassen wir nicht.

01:06:52.440 --> 01:06:56.640
Und wenn Sie nun eine Transaktionsverwaltung entwickeln, dann müssen

01:06:56.640 --> 01:06:58.700
Sie natürlich möglicherweise auch noch diesen Teil mit

01:06:58.700 --> 01:06:59.400
berücksichtigen.

01:06:59.520 --> 01:07:02.800
Also die Frage, halten wir zum Beispiel Ausgaben zurück oder gehen wir

01:07:02.800 --> 01:07:05.120
auf jeden Fall nochmal raus und warnen den Benutzer, dass da irgendwas

01:07:05.120 --> 01:07:06.020
schiefgegangen ist.

01:07:07.940 --> 01:07:13.380
Zur Außenwelt gehört natürlich nicht nur Ausgaben von irgendwelchen

01:07:13.380 --> 01:07:18.880
grafischen Nachrichten auf dem Bildschirm, sondern zur Außenwelt

01:07:18.880 --> 01:07:20.200
gehört, ich bohre ein Loch.

01:07:21.620 --> 01:07:24.000
So, jetzt setzen Sie auch Ihre Transaktion zurück.

01:07:26.120 --> 01:07:27.180
Was machen wir jetzt mit dem Loch?

01:07:30.480 --> 01:07:33.200
Da sieht man auch, dass man zum Beispiel gar nicht einfach

01:07:33.200 --> 01:07:34.000
zurücksetzen kann.

01:07:34.100 --> 01:07:36.480
Man kann zwar eine Transaktion zurücksetzen, im Datenbankbereich ist

01:07:36.480 --> 01:07:38.740
das alles wunderbar, aber in der Außenwelt kann ich nicht

01:07:38.740 --> 01:07:40.180
zurücksetzen, so ohne weiteres.

01:07:40.640 --> 01:07:43.520
Also da werden sogenannte Kompensationsmaßnahmen ergriffen.

01:07:45.780 --> 01:07:49.160
Kompensation heißt, intern muss ich feststellen, das Teil ist halt

01:07:49.160 --> 01:07:53.060
kaputt, wird zum Ausschuss gemacht, dazu setze ich dann nicht direkt

01:07:53.060 --> 01:07:57.120
auf den ursprünglichen Zustand auf, oder ich gehe zwar zum

01:07:57.120 --> 01:07:59.300
ursprünglichen Zustand, aber lasse gleich noch eine sogenannte

01:07:59.300 --> 01:08:02.900
Kompensationstransaktion laufen, die jetzt sozusagen die Datenbasis

01:08:02.900 --> 01:08:03.380
bereinigt.

01:08:03.480 --> 01:08:06.000
Und außen wird natürlich auch angedeutet, dass es sich um ein

01:08:06.000 --> 01:08:06.980
Ausschussstück handelt.

01:08:10.160 --> 01:08:15.080
Oder das Geld springt, das wird aus dem Geldautomaten ausgegeben.

01:08:15.760 --> 01:08:19.340
Kaum ist es da und Sie haben es herausgegriffen, wird Ihnen

01:08:19.340 --> 01:08:22.840
mitgeteilt, dass leider die Transaktion ungültig ist, stecken Sie das

01:08:22.840 --> 01:08:24.000
Geld bitte wieder zurück.

01:08:29.220 --> 01:08:32.300
Da sehen Sie, dass also im Grunde genommen Transaktionsentwurf eine

01:08:32.300 --> 01:08:33.980
ganz schön ekelhafte Angelegenheit ist.

01:08:33.980 --> 01:08:36.600
Wir müssen natürlich doch überlegen, was passiert, wenn es schief

01:08:36.600 --> 01:08:36.940
geht.

01:08:37.600 --> 01:08:40.240
Nur aus Datenbanksicht bin ich aus dem Schneider, denn da kann ich

01:08:40.240 --> 01:08:42.580
natürlich irgendwie reparieren in der Datenbank.

01:08:43.980 --> 01:08:46.300
So, die formale Beschreibung sieht also folgendermaßen aus.

01:08:46.360 --> 01:08:47.900
Wir führen jetzt einfach Operationen ein.

01:08:48.380 --> 01:08:53.120
Ein RI von X, X ist das Datenelement und der Index I bezieht sich mal

01:08:53.120 --> 01:08:55.080
auf die Transaktion, die wir gerade betrachten.

01:08:55.080 --> 01:09:01.160
Also eine Transaktion I liest per RIX, sie schreibt per WIX, sie

01:09:01.160 --> 01:09:09.300
committet per CI oder sie bricht ab per AI für Abort.

01:09:10.300 --> 01:09:15.160
Und wenn wir uns mal nicht dafür interessieren, welche Operation es

01:09:15.160 --> 01:09:17.800
ist, sondern ganz allgemein von Operationen sprechen, werden wir mal

01:09:17.800 --> 01:09:19.420
OI oder OI von X schreiben.

01:09:21.640 --> 01:09:23.840
Und jetzt müssen wir erstmal sagen, was ist eine Transaktion?

01:09:23.980 --> 01:09:25.700
Jetzt Aussicht unserer Transaktionsverwaltung.

01:09:26.500 --> 01:09:27.680
Nun, die hat ein paar Eigenschaften.

01:09:27.760 --> 01:09:29.220
Die erste Eigenschaft ist diese hier.

01:09:30.500 --> 01:09:36.920
Eine Transaktion ist einfach eine Teilmenge aus der Menge der RIX,

01:09:37.040 --> 01:09:41.160
WIX, wobei X irgendein Datenelement ist und dann das Ganze noch

01:09:41.160 --> 01:09:42.860
vereinigt mit AI und CI.

01:09:43.980 --> 01:09:46.920
So what, haben wir ja gerade gesagt.

01:09:47.160 --> 01:09:48.860
Aber dahinter steckt doch mehreres.

01:09:49.600 --> 01:09:54.740
Zum Beispiel, da es sich um eine Teilmenge handelt, definieren wir

01:09:54.740 --> 01:09:57.880
eine Transaktion als etwas, was entweder schon abgeschlossen ist oder

01:09:57.880 --> 01:09:58.620
noch läuft.

01:09:59.540 --> 01:10:02.780
Also es muss noch nicht, wenn wir von einer Transaktion sprechen, dann

01:10:02.780 --> 01:10:06.100
kann da schon AI oder CI erfolgt sein, aber es muss nicht.

01:10:06.100 --> 01:10:08.660
Wir werden hinterher folgendes noch ein bisschen unterscheiden müssen.

01:10:09.020 --> 01:10:11.140
Ist eine Transaktion zum Ende gekommen oder nicht?

01:10:12.940 --> 01:10:15.780
Sie muss also, kann aber, muss nicht abgeschlossen sein.

01:10:15.900 --> 01:10:19.500
Eine erheblich massivere Einschränkung, die wir in dieser Definition

01:10:19.500 --> 01:10:24.780
einführen, ist, ich darf das selbe Datum nur einmal lesen und einmal

01:10:24.780 --> 01:10:25.160
schreiben.

01:10:27.080 --> 01:10:28.480
Da steckt unsere Definition drin.

01:10:28.480 --> 01:10:33.400
Wenn wir also jetzt plötzlich anfangen, in unserem System zuzulassen,

01:10:33.620 --> 01:10:39.400
dass die Transaktion erneut auf ein Datum zugreifen und es nochmal

01:10:39.400 --> 01:10:42.500
schreiben will oder nochmal lesen will, dann ist das in dieser

01:10:42.500 --> 01:10:43.420
Definition nicht drin.

01:10:44.600 --> 01:10:48.180
Jetzt schaffen wir das auch üblicherweise dadurch, dass wir nämlich

01:10:48.180 --> 01:10:51.500
einen großen Puffer haben und ein Element einfach einmal in den Puffer

01:10:51.500 --> 01:10:56.920
eingelesen wird und dann wird von unserer Segmentverwaltung, wird dann

01:10:56.920 --> 01:11:01.520
diese Seite einfach eingefroren im Puffer.

01:11:02.100 --> 01:11:04.260
Bis zum Ende der Transaktion beispielsweise.

01:11:04.500 --> 01:11:07.860
Die kann also erst wieder freigegeben werden und dann auch

01:11:07.860 --> 01:11:11.700
möglicherweise auf den Hintergrundspeicher geschrieben werden, wenn

01:11:11.700 --> 01:11:16.680
die Transaktion zu Ende gekommen ist oder wenn sie zumindest weiß,

01:11:16.800 --> 01:11:18.220
dass das Datenelement nicht mehr braucht.

01:11:20.140 --> 01:11:22.260
Das können wir technisch durchsetzen.

01:11:22.400 --> 01:11:25.400
Aber wir müssen jetzt bedenken, wir bauen unsere ganze Theorie auf,

01:11:25.620 --> 01:11:29.960
auf diese Annahme, dass nur einmal gelesen und einmal geschrieben wird

01:11:29.960 --> 01:11:32.180
in der Transaktion.

01:11:32.860 --> 01:11:35.780
Und wir müssen auf irgendeine Weise, wenn wir die Ergebnisse unserer

01:11:35.780 --> 01:11:38.860
Theorie durchsetzen wollen, zum Beispiel über bestimmte Scheduling

01:11:38.860 --> 01:11:43.820
-Algorithmen erlassen, dann müssen wir eben irgendwie auch zusichern,

01:11:43.940 --> 01:11:46.520
dass eine Transaktion nicht versehentlich das gleiche Element nochmal

01:11:46.520 --> 01:11:48.180
liest oder nochmal schreibt.

01:11:50.160 --> 01:11:53.020
So, und außerdem gibt es aber noch weitere Bedingungen.

01:11:53.360 --> 01:11:58.260
Zunächst einmal, die zweite Bedingung besagt, AI oder CI kann nur

01:11:58.260 --> 01:11:58.920
einmal vorkommen.

01:12:00.400 --> 01:12:04.660
Also in dem Augenblick, wenn ich ein Abort gebe, dann kann ich

01:12:04.660 --> 01:12:05.800
jederjahr noch mit einem Commit ankommen.

01:12:05.800 --> 01:12:08.780
Wenn ich ein Commit gebe, kann ich nicht jederjahr noch mit einem

01:12:08.780 --> 01:12:09.480
Abort ankommen.

01:12:10.120 --> 01:12:11.860
Und ich kann auch keine zwei Commits hintereinander geben.

01:12:12.940 --> 01:12:19.900
Außerdem gebe ich noch eine dritte Bedingung an, nämlich wenn in der

01:12:19.900 --> 01:12:24.760
Transaktion ein AI oder CI vorkommt, dann ist das die letzte Operation

01:12:24.760 --> 01:12:27.920
in unserer Transaktion.

01:12:28.040 --> 01:12:29.200
Das heißt, danach kann ich nichts mehr machen.

01:12:29.980 --> 01:12:32.840
Also ein Versuch, hinterher noch irgendwas mit der Transaktion zu tun,

01:12:33.240 --> 01:12:34.200
ist nicht mehr möglich.

01:12:34.200 --> 01:12:37.380
Das muss man allgemein unserer Transaktionsverwaltung durchsetzen,

01:12:37.460 --> 01:12:40.940
indem sie einfach aufräumt sofort nach dem Commit, sodass die Spuren

01:12:40.940 --> 01:12:42.540
der Transaktion gleich getilgt werden.

01:12:44.020 --> 01:12:50.240
So, und schließlich werden wir noch Folgendes sagen, wenn wir eine

01:12:50.240 --> 01:12:57.540
Folge von RIX und WIX vorkommen, wenn beide vorkommen, dann ist die

01:12:57.540 --> 01:13:00.820
Leseoperation vor der Schreiboperation.

01:13:02.720 --> 01:13:05.940
Also wenn ich ein Element ändern will, dann muss ich es erstmal lesen

01:13:05.940 --> 01:13:07.880
und dann kann ich es wieder schreiben.

01:13:08.420 --> 01:13:10.900
Es muss aber keine Leseoperation da sein, zum Beispiel ein neues

01:13:10.900 --> 01:13:14.240
Element erzeuge, oder einfach der mich der alte Inhalt nicht mehr

01:13:14.240 --> 01:13:17.020
interessiert, dann reicht auch eine reine Schreiboperation.

01:13:17.420 --> 01:13:20.400
Natürlich kann auch eine Leseoperation allein vorkommen, aber wenn

01:13:20.400 --> 01:13:25.140
beide gemeinsam vorkommen, dann nur so, dass erst gelesen wird und

01:13:25.140 --> 01:13:25.920
dann geschrieben wird.

01:13:25.920 --> 01:13:29.720
Also wenn einmal geschrieben worden ist, dann kann dieses Element

01:13:29.720 --> 01:13:31.780
nicht nochmal gelesen werden in unserer Transaktion.

01:13:32.120 --> 01:13:35.180
Das ist so ähnlich wie die Tatsache, dass ich halt keine zwei Schreib-

01:13:35.180 --> 01:13:38.240
oder Leseoperationen auf dem gleichen Element ausführen kann.

01:13:38.940 --> 01:13:41.340
Erleichtert zunächst einmal die Theorie, ist aber auch leicht

01:13:41.340 --> 01:13:41.920
technisch durchzusetzen.

01:13:42.880 --> 01:13:45.460
Also das sind keine absurden Forderungen, sondern die lassen sich

01:13:45.460 --> 01:13:47.060
technisch auch ohne weiteres durchsetzen.

01:13:47.600 --> 01:13:49.740
Also schreiben und anschließend lesen ist auch nicht zulässig.

01:13:50.680 --> 01:13:54.400
So jetzt führe ich mal so eine Reihe von Transaktionen vor, die wir

01:13:54.400 --> 01:13:56.560
als Beispiel nehmen, um so einfach zu illustrieren, was alles

01:13:56.560 --> 01:13:57.160
passieren kann.

01:13:59.780 --> 01:14:03.240
Wir kennen ja unsere Relation schon, jetzt haben wir halt die Buchung,

01:14:03.520 --> 01:14:05.760
die kennen wir ja schon, und dann haben wir unser Ticket, wir nehmen

01:14:05.760 --> 01:14:07.580
also von unseren vier Relationen nur die zwei.

01:14:09.580 --> 01:14:12.900
Und wir wollen mal drei, wir kürzen die ab mit T und B.

01:14:14.700 --> 01:14:18.400
Und ich werde auch hier noch folgendes machen, für das X werden wir

01:14:18.400 --> 01:14:21.180
immer die gesamte Relation einführen, das macht man natürlich in der

01:14:21.180 --> 01:14:24.020
Praxis nicht, sondern man wird auf Tupel zugreifen, aber für die

01:14:24.020 --> 01:14:27.800
Beispiele machen wir uns das Leben einfach und nehmen immer Anlass für

01:14:27.800 --> 01:14:31.660
die gesamte Transaktion, die gesamte Relation in der Transaktion lesen

01:14:31.660 --> 01:14:32.100
oder schreiben.

01:14:32.800 --> 01:14:37.460
Und wir haben drei Transaktionen, eine Transaktion T1, die prüft

01:14:37.460 --> 01:14:40.540
einfach nach, ob Buchung und Passagierliste irgendwie übereinstimmen

01:14:40.540 --> 01:14:41.840
oder ob da ein Fehler passiert ist.

01:14:41.840 --> 01:14:47.500
Die Transaktion T2, die bucht eine Gruppe von Passagieren um, und die

01:14:47.500 --> 01:14:50.760
dritte Transaktion T3, die storniert eine Buchung.

01:14:50.940 --> 01:14:55.020
Also ganz einfache Transaktionen und die lassen wir mal jetzt laufen

01:14:55.020 --> 01:14:58.600
und zunächst sehen wir mal an, wie die in dem Schreiblesemodell

01:14:58.600 --> 01:14:59.060
aussehen.

01:15:00.280 --> 01:15:02.300
Wir nehmen mal an, wir hätten die in SQL formuliert.

01:15:03.180 --> 01:15:04.720
Muss nicht besonders elegant sein.

01:15:05.140 --> 01:15:07.740
Wir nehmen also mal folgendes an, diese Transaktion T1, die die

01:15:07.740 --> 01:15:13.040
Konsistenz überprüft, die druckt für den, schon lange her, 12.

01:15:13.220 --> 01:15:17.680
August 2000, die Zahl der verkauften Tickets aus und dann druckt sie

01:15:17.680 --> 01:15:22.560
außerdem noch aus, wer die Besitzer dieser Tickets sind.

01:15:23.320 --> 01:15:28.560
Und das macht sie folgendermaßen, sie zählt erstmal hier die Zahl der

01:15:28.560 --> 01:15:30.000
Tickets für diesen 12.

01:15:30.120 --> 01:15:33.780
August, die kann man aus der Buchung entnehmen, dann druckt sie die,

01:15:33.780 --> 01:15:35.780
aber da kümmern sie sich weiter drum.

01:15:37.280 --> 01:15:44.100
Dann muss sie nochmal diese Ticketsnähe nochmal sich ansehen und jetzt

01:15:44.100 --> 01:15:48.460
per Verbindungsoperation eben noch den Namen der Ticketinhaber

01:15:48.460 --> 01:15:49.820
auszugeben.

01:15:50.320 --> 01:15:52.820
Und dann druckt sie die Passagierliste aus und dann gibt es ein Commit

01:15:52.820 --> 01:15:53.340
und ist fertig.

01:15:54.980 --> 01:15:57.680
So jetzt wollen wir hier sagen, was passiert denn hier?

01:15:57.920 --> 01:16:02.320
Es wird die Buchung gelesen, dann wird hier Ticket gelesen, die

01:16:02.320 --> 01:16:04.180
Buchung ist ja schon gelesen worden, da brauchen wir nichts mehr zu

01:16:04.180 --> 01:16:04.380
machen.

01:16:05.100 --> 01:16:07.360
Also sieht man, die Transaktionsbeschreibung ist ganz einfach, da

01:16:07.360 --> 01:16:11.520
steht sie unten nämlich, wir lesen erst das B, Buchung, und

01:16:11.520 --> 01:16:16.580
anschließend lesen wir Ticket und wir nehmen an, dass diese zweite

01:16:16.580 --> 01:16:19.420
hier, diese Selectanweisung, da erkennt natürlich unser Übersetzer,

01:16:19.520 --> 01:16:21.600
die steht schon im Puffer, brauchen wir nichts mehr zu machen.

01:16:22.420 --> 01:16:28.180
Also R1 von B, Transaktion hat Index 1 und R1 von T und darauf wird

01:16:28.180 --> 01:16:28.900
das Commit gegeben.

01:16:28.900 --> 01:16:31.640
Also eine ganz einfache Transaktion.

01:16:32.480 --> 01:16:35.440
Aber auch einfache Transaktionen haben gelegentlich ihre Zücken, das

01:16:35.440 --> 01:16:36.400
werden wir an der da schon sehen.

01:16:37.520 --> 01:16:41.060
Die zweite bucht um, auch reichlich idiotisch gebe ich an, die macht

01:16:41.060 --> 01:16:46.440
nämlich folgendes, die stellt fest in der Reihe 19, in der meine

01:16:46.440 --> 01:16:50.620
Mitarbeiter gerade alle eine Reihe gebucht haben, also auf der einen

01:16:50.620 --> 01:16:55.340
Seite, die wollen plötzlich einen Tag früher fliegen und wir haben

01:16:55.340 --> 01:16:58.020
irgendein cleveres System, das stellt fest, dass im vorhergehenden

01:16:58.020 --> 01:17:01.320
Flug auch die gleiche Sitzreihe noch frei ist und bucht dorthin um.

01:17:02.240 --> 01:17:09.320
Das geht also so, dass wir zunächst einmal diejenigen besorgen, die an

01:17:09.320 --> 01:17:11.960
diesem Datum gebucht haben, und zwar in dieser Reihe.

01:17:12.900 --> 01:17:16.340
Und die Umbuchung erfolgt dadurch, dass wir zunächst einmal sagen,

01:17:16.420 --> 01:17:19.580
dazu müssen wir aber ein neues Ticket ausstellen und dieses neue

01:17:19.580 --> 01:17:23.240
Ticket, das sei jetzt mal hier durch irgendeinen Code gekennzeichnet,

01:17:23.460 --> 01:17:27.980
diese Zahl 100.000, die soll an bestimmten Stellen einen Code setzen.

01:17:29.100 --> 01:17:31.260
Und außerdem müssen wir natürlich auch die Buchung ändern, wir müssen

01:17:31.260 --> 01:17:33.120
nämlich sagen, jetzt ist die Sitzreihe am 11.

01:17:33.240 --> 01:17:37.520
August belegt und Sie sehen, was wir da hier tun, ist, dass wir hier

01:17:37.520 --> 01:17:44.300
nochmal das Datum, also hier nochmal die Buchung aufgreifen, wie hier

01:17:44.300 --> 01:17:47.480
oben auch, an dem Datum mit der Sitzreihe und wir sagen einfach,

01:17:47.660 --> 01:17:51.340
ändere aber das Datum ab und ändere die Ticketnummer entsprechend ab.

01:17:52.160 --> 01:17:54.360
Man muss ja bedenken, dass auch da in der Buchung noch die alte

01:17:54.360 --> 01:17:57.140
Ticketnummer steht, die kriegt auch diese Erhöhung hier.

01:17:57.480 --> 01:17:58.900
Ja und jetzt schauen wir wieder an, was passiert.

01:17:59.260 --> 01:18:04.240
Es wird erstmal Buchung gelesen, dann wird Ticket gelesen, dann müssen

01:18:04.240 --> 01:18:05.360
wir das Ticket schreiben.

01:18:06.900 --> 01:18:10.060
Buchung haben wir schon gelesen, also müssen wir außerdem auch nochmal

01:18:10.060 --> 01:18:10.860
die Buchung schreiben.

01:18:11.140 --> 01:18:14.120
Also haben wir erst Buchung gelesen, dann haben wir Ticket gelesen,

01:18:14.120 --> 01:18:17.940
dann schreiben wir das Ticket und dann schreiben wir schließlich die

01:18:17.940 --> 01:18:18.320
Buchung.

01:18:19.240 --> 01:18:22.480
Und wenn wir das wieder anschreiben, was wir übrigens nicht sehen,

01:18:22.600 --> 01:18:25.840
ist, dass die beschriebenen Werte von beiden abhängen.

01:18:25.920 --> 01:18:30.020
Das ist auch noch eine Annahme, die wir später nicht machen dürfen.

01:18:30.100 --> 01:18:33.220
Wir müssen immer sagen, wenn wir irgendwo schreiben, dann müssen wir

01:18:33.220 --> 01:18:37.980
immer annehmen, dass der geschriebene Wert von allen bisher gelesenen

01:18:37.980 --> 01:18:38.740
Werten abhängt.

01:18:38.920 --> 01:18:40.600
Das teilt uns die Transaktion nicht mit.

01:18:40.600 --> 01:18:42.400
Wir müssen also Worst-Case-Annahmen machen.

01:18:42.920 --> 01:18:45.540
Und wir sehen, hier trifft diese Worst-Case-Annahme auch zu.

01:18:46.400 --> 01:18:53.560
Also, um Buchung zu schreiben und um Ticket zu schreiben, müssen wir

01:18:53.560 --> 01:18:55.960
eben sowohl Ticket wie Buchung gelesen haben.

01:18:58.180 --> 01:19:01.600
Halt, da muss noch irgendwo...

01:19:02.360 --> 01:19:03.320
Da oben steht sie noch.

01:19:03.720 --> 01:19:07.020
Wir sehen da oben noch, dass wir jetzt Transaktion C2 haben.

01:19:07.020 --> 01:19:12.100
Wir haben also R2B geschrieben, kurz gefasst R2T, W2T, W2B.

01:19:14.980 --> 01:19:17.160
Die dritte Transaktion ist ziemlich einfach.

01:19:18.580 --> 01:19:22.620
Ich gebe die Ticketnummer vor und sage, bitte storniere das.

01:19:22.740 --> 01:19:25.140
Und jetzt steht die Ticketnummer an zwei Stellen drin, nämlich bei der

01:19:25.140 --> 01:19:28.460
Buchung und in der Relation Ticket.

01:19:28.600 --> 01:19:29.900
Also muss ich aus beiden löschen.

01:19:30.000 --> 01:19:33.040
Das mache ich am besten mit einer Transaktion, weil die Konsistenz

01:19:33.040 --> 01:19:34.580
erst dahinter wieder gewährleistet ist.

01:19:34.580 --> 01:19:40.020
Und man sieht auch deutlich, hier lese ich Ticket, dann schreibe ich

01:19:40.020 --> 01:19:42.280
es wieder, weil ich das gelöschte Tuplen weg muss.

01:19:42.600 --> 01:19:44.780
Dann lese ich Buchung, Schreibbuchung.

01:19:45.960 --> 01:19:48.740
Und infolgedessen sieht die Transaktionsbeschreibung so aus.

01:19:48.880 --> 01:19:55.500
Ich lese erst T, dann lese ich das W, dann schreibe ich das T, dann

01:19:55.500 --> 01:19:57.060
lese ich das B und dann schreibe ich das B.

01:19:57.540 --> 01:19:59.440
Die Transaktionen sind also extrem einfach.

01:20:02.200 --> 01:20:05.020
So, wo siedeln wir jetzt da unseren Scheduler?

01:20:05.400 --> 01:20:06.980
Jetzt müssen wir uns Folgendes vorstellen.

01:20:07.520 --> 01:20:10.580
Der Scheduler, der hat jetzt so eine Menge Transaktionen, die gehen da

01:20:10.580 --> 01:20:10.900
rein.

01:20:11.400 --> 01:20:17.120
Und unser Scheduler, der lauert jetzt auf die Eingaben und erhält

01:20:17.120 --> 01:20:19.940
einen sogenannten Schedule, einen lokalen Schedule.

01:20:20.020 --> 01:20:23.500
Das ist einfach die Abfolge der Operationen, die wir gerade gesehen

01:20:23.500 --> 01:20:26.460
haben, die jetzt bei diesem Scheduler einlaufen.

01:20:26.460 --> 01:20:29.060
Allerdings möglicherweise verzahnt.

01:20:29.760 --> 01:20:32.760
Und unser Scheduler, der muss jetzt da sehen, dass der die

01:20:32.760 --> 01:20:36.460
Isolationseigenschaft durchsetzt, dass da am Ende jede Transaktion

01:20:36.460 --> 01:20:41.860
glaubt, sie sei im Alleinbesitz der Datenbasis und will aber möglichst

01:20:41.860 --> 01:20:43.520
viel Parallelität erreichen.

01:20:44.520 --> 01:20:48.120
Und infolgedessen baut er einen sogenannten globalen Schedule, in dem

01:20:48.120 --> 01:20:51.060
die einfach jetzt verzahnt vorkommen, unsere Operationen.

01:20:51.160 --> 01:20:53.400
Und die liefert dann den Datenbasismanager ab und der

01:20:53.400 --> 01:20:55.900
Datenbasismanager, das ist also unsere Segmentverwaltung, die macht

01:20:55.900 --> 01:21:00.120
dann halt alles, transportiert den Puffer, stellt die Daten bereit und

01:21:00.120 --> 01:21:00.400
so weiter.

01:21:01.360 --> 01:21:03.020
Und muss auch für die Recovery dann sorgen.

01:21:07.340 --> 01:21:08.360
Jetzt können wir mal ansehen.

01:21:09.260 --> 01:21:12.020
Nehmen wir mal an, wir haben also, wir beachten mal nur unsere beiden

01:21:12.020 --> 01:21:13.940
Transaktionen T1 und T2.

01:21:14.160 --> 01:21:16.600
Da stehen sie doch mal, so wie wir sie vorhin aufgestellt haben.

01:21:17.420 --> 01:21:21.060
Und dann könnte man ja sagen, ein solcher verzahnter Schedule könnte

01:21:21.060 --> 01:21:24.400
zum Beispiel folgendes sein, wie die Transaktion T1 läuft los, aber

01:21:24.400 --> 01:21:26.040
schon verliert sie die Kontrolle.

01:21:26.040 --> 01:21:30.080
Unser Scheduler schiebt jetzt erstmal die Transaktion T2 da rein.

01:21:30.940 --> 01:21:32.320
Bis hierhin sogar mit Commit.

01:21:32.880 --> 01:21:36.580
Und dann kommt die Transaktion T1 noch zum Zug und darf ihre zweite

01:21:36.580 --> 01:21:38.040
Leseoperation durchführen.

01:21:38.960 --> 01:21:41.820
Oder könnte auch anders gehen können, zum Beispiel jetzt mal

01:21:41.820 --> 01:21:48.040
umgekehrt, die Transaktion T2 läuft los und dann wird sie hier

01:21:48.040 --> 01:21:52.940
unterbrochen von der Transaktion T1, die allerdings nicht zum Ende

01:21:52.940 --> 01:21:56.600
kommt, sondern bevor die er Commit geben kann, taucht plötzlich wieder

01:21:56.600 --> 01:22:00.520
unsere Transaktion T2 auf, die schließt dann auch tatsächlich bis hier

01:22:00.520 --> 01:22:00.700
ab.

01:22:01.060 --> 01:22:04.160
Und jetzt darf auch noch unsere Transaktion T1 abschließen.

01:22:04.940 --> 01:22:08.700
Und jetzt fragen wir uns nur, sind diese Transaktionen, sind die

01:22:08.700 --> 01:22:11.080
robust, diese beiden Schedules?

01:22:11.700 --> 01:22:13.900
Genügen sie also den Asset-Anforderungen?

01:22:14.220 --> 01:22:16.600
Und übrigens ist das nicht nur eine Frage der Isolation, sondern wie

01:22:16.600 --> 01:22:18.960
wir später noch sehen werden, auch noch der Atomicität.

01:22:18.960 --> 01:22:23.440
Also man muss beide Eigenschaften sogar getrennt betrachten.

01:22:25.140 --> 01:22:27.680
Die Frage ist einfach, sind sie robust oder nicht?

01:22:28.040 --> 01:22:31.400
Und ich wette, wenn Sie das ansehen, können Sie nicht abschätzen.

01:22:32.480 --> 01:22:34.920
Man muss eigentlich so ein bisschen Hintergrundwissen haben oder

01:22:34.920 --> 01:22:38.600
formales Wissen, um zu sagen, ist das ein brauchbarer Schedule oder

01:22:38.600 --> 01:22:39.100
ist das keiner?

01:22:40.920 --> 01:22:42.740
Jetzt betrachten wir mal nur die Isolation.

01:22:43.280 --> 01:22:46.720
Also das heißt, wir haben nur die globale Konsistenz erreicht haben.

01:22:48.940 --> 01:22:51.400
Dann können wir schon mal Folgendes sagen.

01:22:51.960 --> 01:22:53.900
Jetzt geht es um unsere Teilaufgabe.

01:22:54.020 --> 01:22:58.060
Unser Schedule besteht jetzt darin, wir wollen so verzahnen, dass

01:22:58.060 --> 01:22:59.500
Wechselwirkungen vermieden werden.

01:22:59.640 --> 01:23:01.960
Also wir können nicht ganz beliebig die einfach zusammenschaufeln,

01:23:02.260 --> 01:23:04.260
sondern irgendwelche Kriterien müssen wir einhalten, die

01:23:04.260 --> 01:23:07.200
sicherstellen, dass am Ende tatsächlich keine Wechselwirkungen

01:23:07.200 --> 01:23:07.740
auftreten.

01:23:08.260 --> 01:23:12.000
Aber wir wollen das so machen, das heißt, wir wollen einen Maximalgrad

01:23:12.000 --> 01:23:13.280
an Parallelität erreichen.

01:23:15.260 --> 01:23:20.180
Jetzt stellt sich heraus, dass wir am besten mal schon unterscheiden

01:23:20.180 --> 01:23:21.340
zwischen Leser und Schreiber.

01:23:21.940 --> 01:23:27.020
Ein Leser ist eigentlich eine recht harmlose Transaktion, von der man

01:23:27.020 --> 01:23:29.600
sagen kann, Schaden kann die nicht anrichten, denn die ändert ja gar

01:23:29.600 --> 01:23:30.600
nichts an der Datenbasis.

01:23:31.540 --> 01:23:35.760
Während ein Schreiber ist eine gefährliche Transaktion, denn die führt

01:23:35.760 --> 01:23:40.020
ja Änderungen an der Datenbasis durch, hat also insbesondere das

01:23:40.020 --> 01:23:46.560
Potenzial, auch wenn sie lokale Konsistenz gewahrt, dass sie durch

01:23:46.560 --> 01:23:49.600
irgendwelche Interaktionen am Schluss eben doch einen inkonsistenten

01:23:49.600 --> 01:23:50.420
Zustand bewirkt.

01:23:52.180 --> 01:23:57.340
Und jetzt können wir uns gleich überlegen, zwei Leser, die gefährden

01:23:57.340 --> 01:24:00.920
zwei Leser, die jetzt verzahnt ablaufen und auch auf das gleiche

01:24:00.920 --> 01:24:04.300
Datenelement zugreifen, gefährden die die Konsistenz, die globale

01:24:04.300 --> 01:24:05.720
Konsistenz.

01:24:05.720 --> 01:24:06.720
Hier wird genickt, ja.

01:24:07.260 --> 01:24:09.360
Ist auch jemand der Meinung, dass sie nicht gefährdet wird?

01:24:11.300 --> 01:24:13.560
Ja, ich habe zwei Leser, ich habe zwei Leser nur.

01:24:14.300 --> 01:24:16.840
Zwei Leser können keinen Schaden anrichten, die tun ja nichts an der

01:24:16.840 --> 01:24:17.440
Datenbasis.

01:24:18.200 --> 01:24:22.360
Ein Leser und ein Schreiber, wenn die zusammenkommen, ist die globale

01:24:22.360 --> 01:24:23.520
Konsistenz gefährdet?

01:24:27.670 --> 01:24:29.410
Ja, es kommt ein bisschen darauf an, wie wir es definieren.

01:24:30.010 --> 01:24:31.930
Also die Datenbasis selbst ist übrigens nicht in Gefahr.

01:24:32.270 --> 01:24:36.070
Denn wenn nur ein Schreiber da ist und ein Leser, der Leser richtet ja

01:24:36.070 --> 01:24:36.650
keinen Schaden an.

01:24:37.750 --> 01:24:40.570
Also ist der Schreiber, was das Schreiben angeht, ist immer noch

01:24:40.570 --> 01:24:40.910
alleine.

01:24:41.590 --> 01:24:43.150
Also wird er auch keinen Schaden anrichten.

01:24:43.250 --> 01:24:45.310
Was wir aber feststellen werden, er könnte den Leser ärgern.

01:24:47.430 --> 01:24:50.850
Dann, und wenn zwei Schreiber zusammenkommen, dann ist die Katastrophe

01:24:50.850 --> 01:24:53.470
natürlich fällig, in dem Augenblick, die die auf die gleichen Daten

01:24:53.470 --> 01:24:53.970
zugreifen.

01:24:54.930 --> 01:24:57.890
Ja, jetzt, das habe ich also schon gesagt.

01:24:59.530 --> 01:25:00.990
Und jetzt machen wir einfach mal Beispiele.

01:25:02.590 --> 01:25:06.350
Jetzt haben wir also hier unsere erste Transaktion und jetzt sind wir

01:25:06.350 --> 01:25:07.170
also richtig voll da.

01:25:07.850 --> 01:25:11.130
Und die zweite Transaktion mischt sich da mitten rein und dann kommt

01:25:11.130 --> 01:25:11.610
ja die erste.

01:25:11.730 --> 01:25:16.470
Jetzt haben wir also genau den Fall, dass ein Leser läuft, wird aber

01:25:16.470 --> 01:25:20.610
mittendrin unterbrochen durch einen Schreiber, der völlig in einem Zug

01:25:20.610 --> 01:25:21.630
durchgeführt wird.

01:25:22.270 --> 01:25:26.490
Und dann darf der Leser da noch das Ende erreichen.

01:25:27.010 --> 01:25:29.790
Und wenn wir uns das hier ansehen, dann sehen wir auch, es sind hier

01:25:29.790 --> 01:25:32.890
noch markiert unsere Operationen, die wir durchführen, wobei wir uns

01:25:32.890 --> 01:25:36.310
noch einmal erinnern, dass erst das R2B, dann das R2T durchgeführt

01:25:36.310 --> 01:25:37.830
wird, dann W2T, W2B.

01:25:38.170 --> 01:25:42.890
Wir könnten also auch sagen, das ist der uns schon von vorhin bekannte

01:25:42.890 --> 01:25:44.490
Schedule.

01:25:45.570 --> 01:25:49.790
Und jetzt können wir uns ja mal an dem Beispiel der Frage widmen, ob

01:25:49.790 --> 01:25:55.430
denn da nun irgendwie ein gefährliches Ergebnis herauskommt.

01:25:55.610 --> 01:25:57.870
Wir wissen auf jeden Fall, die Datenbasis wird nicht korrumpiert.

01:26:00.490 --> 01:26:02.510
Also hier haben wir unsere beiden Datenbasen.

01:26:02.510 --> 01:26:06.710
Hier rechts ist die Relation Ticket und links unsere Relation Buchung.

01:26:06.850 --> 01:26:07.630
Und es geht mal los.

01:26:10.470 --> 01:26:12.210
R1B, wir marschieren rein.

01:26:12.590 --> 01:26:16.330
Die erste Transaktion stellt also fest, da gibt es in der Tat drei

01:26:16.330 --> 01:26:19.970
Buchungen für dieses Datum.

01:26:20.350 --> 01:26:22.890
Und dann gibt es also brav auch gleich aus, die Anzahl der Tickets ist

01:26:22.890 --> 01:26:23.110
drei.

01:26:23.450 --> 01:26:26.990
Jetzt aber kommt sie nicht weiter, denn es kommt erst unsere Relation

01:26:26.990 --> 01:26:31.590
2, von der ich noch erinnern will, dass die diese Umbuchung da

01:26:31.590 --> 01:26:32.090
vornimmt.

01:26:32.890 --> 01:26:34.650
Die liest natürlich jetzt auch die Buchung.

01:26:35.290 --> 01:26:39.510
Dann liest sie zusätzlich auch noch, übrigens die gleichen Elemente

01:26:39.510 --> 01:26:42.790
natürlich, dann liest sie auch noch hier bei Ticket.

01:26:43.270 --> 01:26:44.730
Jetzt führt sie die Änderung durch.

01:26:44.850 --> 01:26:47.430
Und Sie sehen da so ein bisschen markiert, unterstrichen blau.

01:26:47.890 --> 01:26:50.450
Die hat einfach jetzt diesen Code da reingesetzt, dass das ein

01:26:50.450 --> 01:26:51.390
verändertes Ticket ist.

01:26:52.310 --> 01:26:56.590
Und dann macht sie das gleiche auch noch bei der Buchung.

01:26:57.250 --> 01:26:59.250
Auch da sind jetzt die Änderungen drin.

01:26:59.250 --> 01:27:02.150
Die Ticketnummer hat sich geändert, das Datum hat sich geändert.

01:27:02.530 --> 01:27:05.110
Das macht aber unsere Transaktion 1 ja nichts aus, denn die hat ja die

01:27:05.110 --> 01:27:05.870
Buchung schon gelesen.

01:27:07.390 --> 01:27:11.970
Jetzt kommt die Transaktion 2 und jetzt geht sie aber zu Ticket und

01:27:11.970 --> 01:27:15.170
nimmt die alten Ticketnummer, die sie vorher gelesen hat und die

01:27:15.170 --> 01:27:17.190
findet sie gar nicht mehr drin in Ticket.

01:27:17.390 --> 01:27:18.610
Da sind sie ja geändert worden.

01:27:18.730 --> 01:27:20.910
Also kommt sie raus, es gibt kein Passagier.

01:27:21.970 --> 01:27:24.790
Ergebnis, sie kommt also raus, sagt es gibt drei Passagiere und

01:27:24.790 --> 01:27:26.210
anschließend gibt es eine leere Liste aus.

01:27:26.210 --> 01:27:30.550
Und da werden sie natürlich sagen, die lokale Konsistenz aus meiner

01:27:30.550 --> 01:27:32.710
Sicht als Benutzer, die ist ja wohl nicht gegeben.

01:27:33.110 --> 01:27:35.330
Denn da kommt ein völlig widersprüchliches Ergebnis raus.

01:27:36.030 --> 01:27:41.930
Also wir sehen, wenn sich ein Schreiber bei einem Leser mitten rein

01:27:41.930 --> 01:27:44.470
mischt, dann haben wir ein Problem.

01:27:44.710 --> 01:27:48.210
Und zwar dieses Problem beschreibt man als das Non-Repeatable Read.

01:27:48.850 --> 01:27:50.570
Und das hat mit folgendem zu tun.

01:27:51.890 --> 01:28:01.530
Die Daten, die wir, unsere Relation, sieht zwar immer konsistente

01:28:01.530 --> 01:28:08.430
Zustände, nämlich das erste Lesen der Transaktion 1 war der Zustand am

01:28:08.430 --> 01:28:13.450
Anfang, an ihrem Anfang und der zweite Zustand, den sie gesehen hat,

01:28:13.570 --> 01:28:16.630
nämlich nachdem die Transaktion T2 beendet war, war auch ein

01:28:16.630 --> 01:28:20.010
konsistenter Zustand, nämlich der, der von der Transaktion T2 stammte.

01:28:20.530 --> 01:28:26.310
Nur, leider ist es so, dass die Transaktion selbst den Zustand der

01:28:26.310 --> 01:28:29.050
Daten, den sie liest, sozusagen zu unterschiedlichen

01:28:29.050 --> 01:28:30.470
Gültigkeitszeitpunkten liest.

01:28:30.570 --> 01:28:33.750
Sie liest nämlich einen Zustand, der gültig war zu ihrem Beginn und

01:28:33.750 --> 01:28:36.910
einen weiteren Zustand, der irgendwo mittendrin bei ihr erst gültig

01:28:36.910 --> 01:28:37.570
geworden ist.

01:28:37.890 --> 01:28:41.390
Und man spricht von einem so zeitlich verschmierten an sich zu einem

01:28:41.390 --> 01:28:45.290
konsistenten Zustand, der dann eben inkonsistent ist aus der Sicht der

01:28:45.290 --> 01:28:48.910
Transaktion selbst und einen so zeitlich verschmierten Zustand, das

01:28:48.910 --> 01:28:50.270
nennt man non-repeatable read.

01:28:51.810 --> 01:28:56.550
So, ich werde dann, jetzt machen wir eine kurze Pause, die noch an

01:28:56.550 --> 01:28:59.550
einigen weiteren Transaktionen vorführen, was alles passieren kann.

01:28:59.870 --> 01:29:02.330
Ich würde vorschlagen, dass wir 10 Minuten Pause machen.

01:29:02.870 --> 01:29:05.310
Ich muss ein bisschen vor 13 Uhr nämlich Schluss machen, dann können

01:29:05.310 --> 01:29:06.890
Sie auch etwas früher zum Essen gehen.

01:29:07.150 --> 01:29:11.230
Ich sage mal 10 Minuten Pause, wir treffen uns wieder 11.25 Uhr.

