mirror of
https://gitlab.cs.fau.de/ik15ydit/latexandmore.git
synced 2024-11-22 11:49:32 +01:00
343 lines
13 KiB
TeX
343 lines
13 KiB
TeX
|
\section{Transaktionen}
|
||
|
\subsection{Allgemein}
|
||
|
\subsubsection{Was sind Transaktionen?}
|
||
|
Transaktionen sind eine logische Arbeitseinheit, die mehrere
|
||
|
DB Schritte zusammenfassen.\\
|
||
|
Z.B. einfügen eines neuen Mitarbeiters besteht aus vielen kleinen
|
||
|
DB Befehlen, bis Datenbank wieder konsistent ist
|
||
|
|
||
|
\subsubsection{Wofür sind sie gut?}
|
||
|
Sie überleiten von einem konsistenten Zustand in den nächsten.
|
||
|
Im Fehlerfall muss die Möglichkeit gegeben werden, wieder in
|
||
|
einen konsistenten Zustand zu finden.
|
||
|
Im Mehrfachbetrieb muss gewährleistet werden, dass keine
|
||
|
Nebenläufigkeitsprobleme auftauchen.
|
||
|
|
||
|
\subsubsection{ACID Eigenschaften von Transaktionen:}
|
||
|
\begin{itemize}
|
||
|
\item \textbf{Atomic:} Alle Änderungen von TA werden aktiv oder keine
|
||
|
\item \textbf{Consistency:} TA überführt DB von konsistent in konsistenten Zustand
|
||
|
\item \textbf{Isolation:} TA wird nicht von anderer TA beeinflusst
|
||
|
\item \textbf{Durability:} Änderungen sind Dauerhaft in DB übernommen
|
||
|
\end{itemize}
|
||
|
|
||
|
\subsection{Konsistenzen:}
|
||
|
\subsubsection{Physische Konsistenz:}
|
||
|
Alle Speicheurngsstrukturen sind korrekt. Alle TID's stimmen etc.
|
||
|
|
||
|
\subsubsection{Logische Konsistenz:}
|
||
|
Setzt Physische Konsistenz voraus.\\
|
||
|
Korrektheit der Dateninhalte.\\
|
||
|
Alle Bedingungen des Datenmodells und alle Benutzerdefinierten
|
||
|
Bedingungen sind erfüllt (Assertions).
|
||
|
|
||
|
\subsection{Synchronisation}
|
||
|
\subsubsection{Zustandsdiagramm TA}
|
||
|
\begin{figure}[H]
|
||
|
\begin{center}
|
||
|
\includegraphics[scale=0.6]{TA_status.png}
|
||
|
\caption{Transaktionszustände}
|
||
|
\end{center}
|
||
|
\end{figure}
|
||
|
|
||
|
\subsubsection{Anomalien ohne Synchronisation}
|
||
|
\begin{itemize}
|
||
|
\item \textbf{lost updates}\\
|
||
|
$r_1(x) r_2(x) w_1(x) w_2(x)$
|
||
|
\item Abhängigkeiten von nicht freigegeben Änderungen
|
||
|
\begin{itemize}
|
||
|
\item \textbf{dirty read}\\
|
||
|
$w_1(x)r_2(x)a_1 c_2$\\
|
||
|
Änderung wird noch nicht freigegeben (ggf abgebrochen) aber trotzdem gelesen
|
||
|
\item \textbf{dirty write}\\
|
||
|
$w_1(x)r_2(x)w_2(x)a_1 c_2$\\
|
||
|
Änderung wird noch nicht freigegeben (ggf abgebrochen) aber trotzdem geschrieben
|
||
|
\end{itemize}
|
||
|
\item \textbf{Non Repeatable Read}\\
|
||
|
$r_1(x)w_2(x)r_1(x)$\\
|
||
|
T1 sieht beim erneuten lesen einen anderen Wert als zuvor
|
||
|
\item \textbf{Phantom}\\
|
||
|
$r_1(P)w_2(x in P)r_1(P)$\\
|
||
|
Wie bei \textit{Non Repeatable Read} nur Prädikat statt einzelnes Element
|
||
|
\end{itemize}
|
||
|
\textit{Legende: c = commit, a = abort, w = write, r = read}
|
||
|
\subsubsection{Serialisierung}
|
||
|
Hintereinanderausführung aller TA's. Problem werden
|
||
|
sehr große Wartezeiten. Allgemein ist deine Datenbank für Mehrbenutzerbetrieb
|
||
|
ausgelegt, dies würde ab adsurdum geführt durch Serialisierung.
|
||
|
Was tun im Fehlerfall
|
||
|
|
||
|
\subsubsection{Serialisierbarkeit}
|
||
|
Ziel:\\TA's laufen \textit{verzahnt} ab, aber ihr Ergebnis gleicht dem eines seriellen
|
||
|
Ablaufes.\\
|
||
|
$\rightarrow$ Ein Schedule von TA's ist \textbf{serialisierbar}, wenn es einen äquivalten
|
||
|
\textbf{seriellen} Ablauf gibt.
|
||
|
|
||
|
\subsubsection{Implementierung von Sperren}
|
||
|
\textbf{Wann sperren?}\\
|
||
|
Statisch:\\
|
||
|
Alles sperren was evtl gebraucht wir (preclaiming)
|
||
|
|
||
|
Dynamisch:\\
|
||
|
Zur Laufzeit von TA nach Bedarf sperren\\
|
||
|
$\rightarrow$ Gefahr von Verklemmungen!
|
||
|
|
||
|
Sperrgranulat:\\
|
||
|
Warum nicht Tupel:
|
||
|
\begin{itemize}
|
||
|
\item Nicht immer effizient, bei großen Mengen
|
||
|
\item Phantom Tupel; es können nur bereits existente Tupel gesperrt werden.
|
||
|
\end{itemize}
|
||
|
Deshalb wird \textit{hierarchische Schachtelung} der Datenobjekte:\\
|
||
|
\begin{figure}[H]
|
||
|
\begin{center}
|
||
|
\includegraphics[scale=0.8]{sperrgranulat.png}
|
||
|
\caption{Sperrgranulate}
|
||
|
\end{center}
|
||
|
\end{figure}
|
||
|
|
||
|
Für jedes Objekt kann man nun einen Sperrmodus vergeben.
|
||
|
Andere TA können daran erkennen, ob sie ihre Aktion ausführen dürfen.
|
||
|
\begin{figure}[H]
|
||
|
\begin{center}
|
||
|
\includegraphics[scale=0.6]{komp_matrix.png}
|
||
|
\caption{Kompatibilitätsmatrix}
|
||
|
\end{center}
|
||
|
\end{figure}
|
||
|
Das Problem an dieser Art der Sperrung ist, dass
|
||
|
\begin{itemize}
|
||
|
\item Alle Nachfolgeknoten implizit mitgesperrt werden
|
||
|
\item Alle Vorgängerknoten auch gesperrt werden müssen
|
||
|
\end{itemize}
|
||
|
Daher werden sogenannte \textbf{(Intention) Anwartschaftssperren} eingeführt:
|
||
|
\begin{itemize}
|
||
|
\item {IS Sperre:\\
|
||
|
falls auf untergeordnete Objekte lesend zugegriffen wird}
|
||
|
\item {IX Sperre:\\
|
||
|
falls auf untergeordnete schreibend zugegriffen wird}
|
||
|
\end{itemize}
|
||
|
$\rightarrow$ Benutzung von Untersperre wird angezeigt, aber nochmal explizit weiter unten gesetzt!
|
||
|
\paragraph{TOP-DOWN bei Sperre}
|
||
|
\begin{itemize}
|
||
|
\item Bevor ein Knoten mit S oder IS gesperrt werden darf, müssen alle Vorgänger
|
||
|
in der Hierarchie im IX- oder im IS-Modus gesperrt worden sein.
|
||
|
\item
|
||
|
Bevor ein Knoten mit X oder IX gesperrt werden darf, müssen alle Vorgänger
|
||
|
in der Hierarchie im IX-Modus gesperrt worden sein.
|
||
|
\end{itemize}
|
||
|
\paragraph{BOTTOM-UP bei Freigabe}
|
||
|
\begin{itemize}
|
||
|
\item Freigabe von unten nach oben
|
||
|
\item kein Knoten darf entsperrt werden, wenn noch andere Nachfolger dieses Knotens
|
||
|
gesperrt sind
|
||
|
\end{itemize}
|
||
|
Als Optimierung gibt es noch die \textbf{SIX} Sperre. Alles wird lesend gesperrt
|
||
|
und eine Menge an Nachfolgern schreibend. Das lohnt sich z.B. wenn aus einer Relation
|
||
|
nur wenige Tupel verändert werden.
|
||
|
|
||
|
\subsubsection{Probleme beim Sperren}
|
||
|
\begin{itemize}
|
||
|
\item Sperren muss sehr schnell gehen, da Anforderungen sehr hoch
|
||
|
\item halten von Sperren bis TA-ende führt zu langen Wartezeiten
|
||
|
\item Eigenschaften des Schemas können \glqq hotspots\grqq erzeugen
|
||
|
\item {Optimierungen:
|
||
|
\begin{itemize}
|
||
|
\item Nutzung mehrere Objektversionen
|
||
|
\item spezialisiertes Sperren
|
||
|
\item Änderungen auf privaten Objektkopien
|
||
|
\end{itemize}
|
||
|
}
|
||
|
\end{itemize}
|
||
|
|
||
|
\subsubsection{Verklemmungen}
|
||
|
Lösungsmöglichkeiten:
|
||
|
\begin{itemize}
|
||
|
\item{\textbf{Timout:}\\
|
||
|
Transaktion nach bestimmter Wartezeit zurücksetzen.\\
|
||
|
$\rightarrow$ problematisch Länge des Timeouts zu bestimmen
|
||
|
}
|
||
|
\item{\textbf{Verhütung (Prevention)}\\
|
||
|
Durch Preclaiming (s.o.) keine Deadlock Verhinderung zur Laufzeit notwenig.}
|
||
|
\item{\textbf{Vermeidung (Avoidance)}\\
|
||
|
Potentielle Deadlocks im vorhinein erkennen und vermeiden\\
|
||
|
$\rightarrow$ Laufzeitunterstützung notwendig
|
||
|
}
|
||
|
\item{\textbf{Erkennung (Detection)}\\
|
||
|
Explizites führen eines Wartegraphen und darin Zyklensuche. Im Zyklus dann
|
||
|
eine oder mehrere (am besten billigste) TA zurücksetzen.}
|
||
|
\end{itemize}
|
||
|
\textbox{Deadlock - nicht serialisierbarer Schedule}{
|
||
|
Nicht serialisierbare Schedules, beschreibt Abläufe die zu
|
||
|
keinem seriellen Ablauf äquivalent sind. Die somit zu Deadlocks führen.
|
||
|
Führt man diese mit \textit{dynamischen} Sperren aus, muss es aber nicht
|
||
|
zwangsläufig auch zu Deadlocks kommen!
|
||
|
}
|
||
|
\subsection{Recovery}
|
||
|
\textbf{Recovery Klassen:}
|
||
|
\begin{itemize}
|
||
|
\item {Partial Undo (R1-Recover)
|
||
|
\begin{itemize}
|
||
|
\item nach Transaktionsfehler
|
||
|
\item isoliertes und vollständiges Zurücksetzen der Daten
|
||
|
in Anfangszustand
|
||
|
\item beeinflusst andere TA nicht
|
||
|
\end{itemize}
|
||
|
}
|
||
|
\item {Partial Redo (R2-Recover)
|
||
|
\begin{itemize}
|
||
|
\item nach Systemfehler (mit Verlust von HS)
|
||
|
\item Wiederhlung aller verlorengegangenen Änderungen
|
||
|
(waren nur im Puffer) von abgeschlossenen TA
|
||
|
\end{itemize}
|
||
|
}
|
||
|
\item {Global Undo (R3-Recover)
|
||
|
\begin{itemize}
|
||
|
\item nach Systemfehler (mit Verlust von HS)
|
||
|
\item Zurücksetzen aller durch Ausfall unterbrochenen TA
|
||
|
\end{itemize}
|
||
|
}
|
||
|
\item {Global Redo (R4-Recover)
|
||
|
\begin{itemize}
|
||
|
\item nach Gerätefehler
|
||
|
\item Einspielen von Archivkopie und nachvollziehen
|
||
|
aller beendeten TA's
|
||
|
\end{itemize}
|
||
|
}
|
||
|
\end{itemize}
|
||
|
\subsubsection{Archivkopien}
|
||
|
Arten:
|
||
|
\begin{itemize}
|
||
|
\item \glqq cold backup\grqq: DBS muss au"ser Betrieb sein
|
||
|
\item \glqq hot backup\grqq: Beeinträchtigung des laufenden Betriebs
|
||
|
\end{itemize}
|
||
|
\subsubsection{Einbringstrategien}
|
||
|
Wann werden geänderte Daten aus dem Puffer auf die Platte geschrieben?
|
||
|
\begin{itemize}
|
||
|
\item {STEAL:\\
|
||
|
Bei Verdrängung au dem Puffer, auch vor ende der Transaktion}
|
||
|
\item {NO STEAL:\\
|
||
|
Frühestens am Ende der Transaktion $\rightarrow$ kein UNDO erfoderlich (aber großen Puffer)}
|
||
|
|
||
|
\item {FORCE:\\
|
||
|
Spätestens am Ende der Transaktion $\rightarrow$ kein Partial Redo erfoderlich}
|
||
|
|
||
|
\item {NO FORCE:\\
|
||
|
Erst bei Verdränung aus dem Puffer}
|
||
|
\end{itemize}
|
||
|
Wie werden geänderte Daten aus dem Puffer auf Platte geschrieben?
|
||
|
\begin{itemize}
|
||
|
\item{ATOMIC:\\
|
||
|
Indirekte Einbringstrategie.\\
|
||
|
Ununterbrechbares Umschalten}
|
||
|
\item{NOT ATOMIC:
|
||
|
Direkte Einbringstrategie.\\
|
||
|
Ist nicht ununterbrechbar.
|
||
|
}
|
||
|
\end{itemize}
|
||
|
\subsubsection{Protokolldaten}
|
||
|
Als Protollinformation zählt was über die Einbringungsstrategie hinaus
|
||
|
benötigt wird, um nach einem Systemausfall den jüngsten konsisten Zustand
|
||
|
wiederherzustellen.
|
||
|
\begin{figure}[H]
|
||
|
\begin{center}
|
||
|
\includegraphics[scale=0.6]{protokoll2.png}
|
||
|
\caption{Protokollinformationen}
|
||
|
\end{center}
|
||
|
\end{figure}
|
||
|
|
||
|
\paragraph{Wann wird in Protokolldatei geschrieben?}
|
||
|
\begin{itemize}
|
||
|
\item{UNDO-Information:\\
|
||
|
\begin{itemize}
|
||
|
\item bevor die zugehörigen Änderungen in Datenbestand eingebracht werden
|
||
|
\item sonst rücksetzen unmöglich
|
||
|
\end{itemize}
|
||
|
}
|
||
|
\item{REDO-Information:\\
|
||
|
\begin{itemize}
|
||
|
\item muss geschrieben sein (in tmp Log Datei und Archivdatei), bevor der Abschluss der TA
|
||
|
an Programm bzw Benutzer gemeldet wird
|
||
|
\item sonst Wiederherstellung nicht möglich
|
||
|
\end{itemize}
|
||
|
}
|
||
|
\end{itemize}
|
||
|
\subsubsection{Backward-/Forward Recovery}
|
||
|
\begin{enumerate}
|
||
|
\item{ Forward:\\
|
||
|
Änderungen sind noch nicht in DB, aber schon in Log. Bevor
|
||
|
diese auf DB geschrieben werden, wird ein Commit-Record in
|
||
|
Log File geschrieben. Falls was schief geht und der Commit Record noch da ist, werden alle diese Änderungen wiedehrolt und ansonsten nichts getan, da alte Version noch in DB steht.}
|
||
|
\item{ Backward:\\
|
||
|
Ins Log kommt immer \textbf{alte} Version eines Wertes. Bei
|
||
|
einem Commit wird gewartet bis alle neuen werte in DB stehen.
|
||
|
Danach erst wird CommitRecord erstellt und eine Bestätigung
|
||
|
signalisiert.
|
||
|
Bei Verlust werden entweder alte Daten hergestellt oder nichts getan.}
|
||
|
\end{enumerate}
|
||
|
\paragraph{Vergleich}
|
||
|
\begin{itemize}
|
||
|
\item{ Forward Recovery: Hoher Speicherplatzbedarf! Daten werden erst nach Beendigung der TA in DB geschrieben und deswegen solange in Puffer behalten}
|
||
|
\item{ Backward-Recovery: Hoher I/O Aufwand! Alle Änderungen müssen vor TA-Ende in Datenfiles stehen.}
|
||
|
\end{itemize}
|
||
|
\subsubsection{Undo-/Redo Logging}
|
||
|
Verbesserung zu Backward-/Forward Recovery.
|
||
|
\begin{figure}[H]
|
||
|
\begin{center}
|
||
|
\includegraphics[scale=0.8]{protokoll.png}
|
||
|
\caption{Physische Protokollierung}
|
||
|
\end{center}
|
||
|
\end{figure}
|
||
|
Zustände vor bzw nach einer Änderungen werden protokolliert:
|
||
|
\begin{itemize}
|
||
|
\item alter Zustand: Before Image (BI) für UNDO
|
||
|
\item neuer Zustand: After Image (AI) für REDO
|
||
|
\item für jede veränderte Seite (3) wird jeweils eine
|
||
|
vollständige Kopie vor (2) und nach (4) der Änderung in den Log
|
||
|
geschrieben.\\
|
||
|
$+$ schnelle Recovery\\
|
||
|
$-$ hoher E/A Aufwand
|
||
|
\end{itemize}
|
||
|
\paragraph{Optimierungen}
|
||
|
Um Log-Aufwand zu reduzieren nur geänderte \textbf{Teile einer Seite}
|
||
|
protokollieren.\\
|
||
|
Sammlung und Pufferung im HS:
|
||
|
\begin{itemize}
|
||
|
\item $+$ reduzierter E/A Aufwand
|
||
|
\item $-$ komplexeres und zeitaufwändigeres Recovery\\
|
||
|
Zurückspeichern gleicht eher dem Neu einfügen (freien Platz suchen, TID vergeben), da Stelle von wo Einträge stammen andersweitig genutzt werden können
|
||
|
\end{itemize}
|
||
|
|
||
|
\subsubsection{Sicherungspunkte}
|
||
|
Ma"snahmen zur Begrenzung des REDO Aufwands nach Systemfehlern (alle
|
||
|
erfolgreichen Änderungen die im Puffer verloren gegangen sind müssen wiederholt werden $\rightarrow$ nicht praktikabel!
|
||
|
\paragraph*{Methoden}
|
||
|
\begin{itemize}
|
||
|
\item{ \textbf{Transaction-Oriented Checkpoint}\\
|
||
|
Geänderte Seiten einer TA nach TA-ende sofort in DB bringen (siehe FORCE) $\rightarrow$ zu hohe Belastung}
|
||
|
\item{ \textbf{ Transaction-COnsisten Checkpoint}
|
||
|
\begin{itemize}
|
||
|
\item Einbringung aller Änderung erfolgreicher TA's
|
||
|
\item Lesesperee auf ganzer DB zum Zeitpunkt des Sicherungspunktes
|
||
|
\item Verzögerung von TA's
|
||
|
\item Sicherungspunkt begrenzt Undo und Redo Recovery
|
||
|
\end{itemize}
|
||
|
}
|
||
|
\item{ \textbf{Action-Consisten Checkpoint}
|
||
|
\begin{itemize}
|
||
|
\item Zum Zeitpunkt des Sicherungspunktes dürfen keine Änderunen aktiv sein
|
||
|
\item Begünstigt nur Recovery, dafür kürzere Totzeit von System
|
||
|
\end{itemize}
|
||
|
}
|
||
|
\end{itemize}
|
||
|
\subsubsection{Allgemeine Restart Prozedur}
|
||
|
\textbf{3-phasiger Ansatz}
|
||
|
\begin{enumerate}
|
||
|
\item Analyse Lauf
|
||
|
Vom letzten Checkpoint bis zum Log Ende. Bestimmung von Gewinner und Verlierer TA's, sowie Seiten, die von ihnen geändert wurden
|
||
|
\item Undo Lauf \\
|
||
|
Rücksetzen der Verlierer TA's durch Rückwärtslesen des Logs bis zum BOT Satz der ältesten Verlierer TA
|
||
|
\item Redo Lauf \\
|
||
|
Vorwärtslesen des Logs (Startpunkt abhängig von Checkpoint Typ) und Änderungen der Gewinner TA's wiederholen
|
||
|
\end{enumerate}
|
||
|
|