Deadlocks

Deadlocks treten auf, wenn sich mehrere Tasks dauerhaft gegenseitig blockieren, weil jeder der Tasks eine Sperre für eine Ressource aufrecht erhält, die von den anderen Tasks zu sperren versucht wird. Beispiel:

  • Die Transaktion A richtet eine freigegebene Sperre für Zeile 1 ein.

  • Die Transaktion B richtet eine freigegebene Sperre für Zeile 2 ein.

  • Die Transaktion A fordert nun eine exklusive Sperre für Zeile 2 an und ist blockiert, bis die Transaktion B beendet ist und die freigegebene Sperre für Zeile 2 aufhebt.

  • Die Transaktion B fordert nun eine exklusive Sperre für Zeile 1 an und ist blockiert, bis die Transaktion A beendet ist und die freigegebene Sperre für Zeile 1 aufhebt.

Folglich kann Transaktion A nicht abgeschlossen werden, bis die Transaktion B abgeschlossen ist. Die Transaktion B ist aber durch Transaktion A blockiert. Diese Bedingung wird auch zyklische Abhängigkeit genannt: die Transaktion A ist von der Transaktion B abhängig und die Transaktion B schließt den Kreis wieder, da sie von der Transaktion A abhängig ist.

Die beiden Transaktionen, die sich im Deadlock befinden, werden auf unbegrenzte Zeit aufeinander warten, es sei denn, der Deadlock wird von einem externen Prozess unterbrochen. Der Deadlockmonitor des Microsoft SQL Server Database Engine (Datenbankmodul) überprüft regelmäßig, ob sich Tasks in einem Deadlock befinden. Wenn der Monitor eine solche zyklische Abhängigkeit erkennt, wählt er einen der Tasks als Opfer aus und beendet dessen Transaktion mit einem Fehler. Dies ermöglicht dem anderen Task, seine Transaktion abzuschließen. Die Anwendung mit der Transaktion, die mit einem Fehler beendet wurde, kann nun erneut versuchen, die Transaktion auszuführen. Dies gelingt nun normalerweise, nachdem die andere, an dem Deadlock beteiligte Transaktion bereits abgeschlossen ist.

Das Verwenden bestimmter Codierungskonventionen kann die Wahrscheinlichkeit, dass Anwendungen Deadlocks verursachen, verringern. Weitere Informationen finden Sie unter Minimieren von Deadlocks.

Deadlocks werden oft mit normalen Blockierungen verwechselt. Wenn eine Transaktion eine Sperre für eine Ressource anfordert, die bereits von einer anderen Transaktion gesperrt ist, wartet die anfordernde Transaktion, bis die Sperre aufgehoben wird. Standardmäßig treten bei SQL Server-Transaktionen keine Timeouts auf, es sei denn, LOCK_TIMEOUT wurde festgelegt. Die anfordernde Transaktion ist also blockiert, befindet sich aber nicht in einem Deadlock, da sie ihrerseits die andere Transaktion, die im Besitz der Sperre ist, nicht blockiert. Die Transaktion, die die Sperre besitzt, wird zu gegebener Zeit abgeschlossen und die Sperre aufgehoben, woraufhin die anfordernde Transaktion die Sperre erhält und den Transaktionsvorgang ausführt.

Deadlocks werden manchmal auch "deadly embrace" (tödliche Umarmung) genannt.

Ein Deadlock ist eine Bedingung, die in jedem System mit mehreren Threads auftreten kann, nicht nur bei Managementsystemen für relationale Datenbanken, sowie in anderen Ressourcen als Sperren für Datenbankobjekte. Ein Thread in einem Multithread-Betriebssystem kann beispielsweise eine Ressource oder mehrere Ressourcen, wie z. B. Speicherblöcke, reservieren. Wenn sich die zu reservierende Ressource derzeit im Besitz eines anderen Threads befindet, muss der erste Thread eventuell warten, bis der Besitzerthread die Zielressource freigegeben hat. Der wartende Thread ist für diese bestimmte Ressource abhängig vom Besitzerthread. In einer Instanz von Database Engine (Datenbankmodul) können Sitzungen beim Reservieren von anderen als Datenbankressourcen, wie z. B. Speicher oder Threads, in eine Deadlocksituation geraten.

Diagramm mit Transaktionsdeadlock

In der Abbildung weist Transaktion T1 eine Abhängigkeit von Transaktion T2 für die Sperrressource der Part-Tabelle auf. Entsprechend weist Transaktion T2 eine Abhängigkeit von Transaktion T1 für die Sperrressource der Supplier-Tabelle auf. Da diese Abhängigkeiten einen Kreis bilden, besteht ein Deadlock zwischen den Transaktionen T1 und T2.

Deadlocks können auch auftreten, wenn eine Tabelle partitioniert wird und für die LOCK_ESCALATION-Einstellung von ALTER TABLE die Option AUTO festgelegt ist. Ist für LOCK_ESCALATION die Option AUTO festgelegt, nimmt die Parallelität durch Unterstützung der Sperre von Tabellenpartitionen auf HoBT-Ebene anstatt auf TABLE-Ebene durch Database Engine (Datenbankmodul) zu. Wenn jedoch separate Transaktionen Partitionssperren in eine Tabelle aufnehmen und in der anderen Partitionstransaktion eine Sperre hinzugefügt werden soll, wird hiermit ein Deadlock verursacht. Diese Art Deadlock kann durch Festlegen von TABLE für LOCK_ESCALATION vermieden werden, auch wenn mit dieser Einstellung die Parallelität verringert wird, indem große Aktualisierungen gezwungen werden, auf eine Tabellensperre zu warten.