Wissen

Praxis-Artikel und Buchkapitel zu SQL-Performance, Sicherheit und Hochverfügbarkeit – alle frei verfügbar.

Beratung

Festpreis-Analyse mit Bericht und Handlungsempfehlung – oder strategische Begleitung bei Architektur, Migration und Hochverfügbarkeit.

Fachbücher

Die fünfbändige Reihe „Ulis SQL-Bibliothek“ – Band 1 verfügbar. Leseprobe herunterladen!

Tools

UB.SimSQL: SQL-Server-Lastsimulator mit regelbasierten Konfigurationsempfehlungen. Lokal, ohne Cloud, ohne Abo.

Schulungen

Online-Workshops zu Performance, Sicherheit und Entwicklung – kompakt, hands-on, ohne MOC-Folienschlacht.

SQL Server Deadlocks analysieren und beheben

Vereinzelte Deadlocks sind Alltag — Wellen sind ein Konstruktionsfehler

Deadlock-Wellen analysieren und beheben

Vereinzelte Deadlocks sind Alltag — Wellen sind ein Konstruktionsfehler. So liest du den Graph und findest die Ursache.

Es ist Dienstagvormittag, 10:47 Uhr. Bei der Musterwerk GmbH läuft seit dem Wochenende die neue Version der Lagerverwaltung, und seitdem hagelt es Fehlermeldungen: Transaction (Process ID 84) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Nicht einmal, nicht zweimal — das Monitoring zählt 340 Stück seit Mitternacht. Der Hersteller der Anwendung sagt, das sei „ein Datenbankproblem“. Der Hoster sagt, der Server sei „grün“. Und der Fachbereich sagt gar nichts mehr, weil jede dritte Buchung mit einem Fehler abbricht.

Willkommen bei den Deadlock-Wellen. Ein einzelner Deadlock pro Tag ist kein Drama — SQL Server ist dafür gebaut, ihn sauber aufzulösen. Aber Wellen von Deadlocks sind nie Pech und nie Zufall: Sie sind ein strukturelles Problem im Zusammenspiel von Code, Indizes und Sperren, und sie lassen sich systematisch diagnostizieren. Dieser Beitrag aus dem SQL-Server-Notarztwagen (die Triage-Übersicht liegt unter /sql-server-notarztwagen/) zeigt dir, wo die Deadlock-Daten längst auf dich warten, wie du den Graph liest — und welche fünf Muster hinter fast allen Wellen stecken.

Was bedeutet Deadlock technisch?

Ein Deadlock ist eine zirkuläre Verklemmung: Session A hält eine Sperre auf Ressource 1 und will zusätzlich Ressource 2. Session B hält die Sperre auf Ressource 2 und will Ressource 1. Beide warten aufeinander, keiner kommt je ans Ziel — der Kreis ist geschlossen. Ohne Eingriff stünden beide Sessions bis zum Jüngsten Tag. Deshalb läuft im SQL Server der Deadlock-Monitor: Er prüft standardmäßig alle fünf Sekunden den Wartegraphen, erkennt geschlossene Kreise und löst sie auf — indem er eine der beteiligten Sessions opfert.

Das Opfer — im Jargon das Deadlock Victim — bekommt Error 1205, seine Transaktion wird zurückgerollt, und die Sperren werden freigegeben, damit der andere Prozess weiterarbeiten kann. Gewählt wird im Normalfall die Session mit den geringsten Rollback-Kosten — also die, deren bisherige Änderungen am billigsten rückgängig zu machen sind. Mit SET DEADLOCK_PRIORITY lässt sich diese Wahl beeinflussen: Eine Session mit niedrigerer Priorität wird bevorzugt geopfert. Das ist gelegentlich nützlich (ein nächtlicher Wartungsjob darf gern das Opfer sein, die Kassenbuchung nicht), aber kein Heilmittel — es verschiebt nur, wer den Schaden hat.

Die wichtigste Abgrenzung gleich vorweg, weil sie in jeder zweiten Eskalations-Telko durcheinandergeht: Blocking ist kein Deadlock. Beim Blocking wartet eine Session auf eine andere — unangenehm, aber endlich: Sobald der Blocker committet, geht es weiter. Beim Deadlock warten zwei (oder mehr) Sessions gegenseitig aufeinander, und ohne den Monitor ginge es nie weiter. Praktische Folge: Blocking erzeugt Langsamkeit, Deadlocks erzeugen Fehler. Wenn deine Anwendung Timeouts wirft, schau in den Blocking-Beitrag des Notarztwagens. Wenn sie Error 1205 wirft, bist du hier richtig.

Abgrenzung: Deadlock vs. Blocking

Deadlock — zirkuläres Warten, löst sich nie von selbst. Der Deadlock-Monitor opfert eine Session, die Anwendung sieht Error 1205. Symptom: Fehler.
Blocking — lineares Warten, löst sich auf, sobald der Blocker fertig ist. Die Anwendung sieht bestenfalls nichts, schlimmstenfalls Timeouts. Symptom: Langsamkeit.
Faustregel: 1205 im Log = Deadlock. Wartende Sessions ohne Fehler = Blocking — dafür gibt es den Beitrag zu Blocking-Kaskaden (/sql-server-blocking/).

Der Diagnose-Pfad: den Deadlock-Graph lesen

Das zentrale Beweismittel ist der Deadlock-Graph — eine XML-Aufzeichnung, die der Server bei jedem Deadlock erstellt. Sie enthält die beteiligten Prozesse samt ihrer Statements, die umkämpften Ressourcen und die Owner-/Waiter-Beziehungen. Die folgende Skizze zeigt das häufigste Szenario: zwei Sessions, zwei Tabellen, gegenläufige Zugriffsreihenfolge.

Beim Lesen interessieren dich drei Fragen, immer in dieser Reihenfolge: Erstens, welche Statements sind beteiligt (im XML der inputbuf-Block je Prozess)? Zweitens, welche Ressourcen werden umkämpft — Key Lock, Page Lock, ganze Objekte? Drittens, in welcher Reihenfolge haben die Prozesse zugegriffen? Bei Wellen lohnt der Blick auf zehn, zwanzig Graphen nebeneinander: Wiederholen sich dieselben Statements und Ressourcen, hast du dein Muster — und damit den Hebel.

Erste Diagnose: konkrete Skripte

Die beste Nachricht des Tages: Du musst nichts nachträglich aktivieren. Die immer laufende system_health-Session zeichnet jeden Deadlock als xml_deadlock_report auf. Das folgende Skript holt die Graphen der letzten Zeit aus dem Ring Buffer:

— Deadlock-Graphen aus der system_health-Session ziehen

SELECT CONVERT(xml, event_data).value(

'(event/@timestamp)[1]', 'datetime2') AS Zeitpunkt,

CONVERT(xml, event_data).query(

'/event/data/value/deadlock') AS DeadlockGraph

FROM sys.fn_xe_file_target_read_file(

'system_health*.xel', NULL, NULL, NULL)

WHERE object_name = 'xml_deadlock_report'

ORDER BY Zeitpunkt DESC;

Klicke in SSMS auf das XML, speichere es als .xdl und öffne die Datei erneut in SSMS — dann bekommst du die grafische Darstellung mit Prozessen, Ressourcen und dem blauen Kreuz auf dem Victim. Verdächtig ist alles, was sich wiederholt: dieselben zwei Prozeduren, dieselbe Tabelle, derselbe Index. Eine Welle hat fast immer ein dominantes Muster — finde es, statt jeden Deadlock einzeln zu betrauern.

Die system_health rolliert allerdings: Bei viel Betrieb sind ältere Ereignisse schnell verdrängt. Für die Analyse einer laufenden Welle — und als dauerhaftes Frühwarnsystem — richtest du eine eigene XE-Session mit File-Target ein:

— Dedizierte Deadlock-Session mit File-Target

CREATE EVENT SESSION [DeadlockCapture] ON SERVER

ADD EVENT sqlserver.xml_deadlock_report

ADD TARGET package0.event_file (

SET filename = N'DeadlockCapture',

max_file_size = 50,

max_rollover_files = 4

)

WITH (STARTUP_STATE = ON);

GO

ALTER EVENT SESSION [DeadlockCapture] ON SERVER STATE = START;

Drittes Werkzeug für den Blick aufs große Ganze: die Sperren-Landschaft während der Welle. Häufen sich exklusive Sperren auf einem bestimmten Objekt, weißt du, wo der Kampfplatz liegt — und ob womöglich Lock Escalation im Spiel ist:

— Wer haelt welche Sperren auf welchen Objekten?

SELECT tl.request_session_id AS SPID,

DB_NAME(tl.resource_database_id) AS Datenbank,

tl.resource_type, — KEY, PAGE, OBJECT …

tl.request_mode, — S, U, X, IX …

tl.request_status, — GRANT oder WAIT

OBJECT_NAME(p.object_id) AS Objekt

FROM sys.dm_tran_locks AS tl

LEFT JOIN sys.partitions AS p

ON p.hobt_id = tl.resource_associated_entity_id

WHERE tl.resource_database_id = DB_ID()

ORDER BY tl.request_session_id;

Die häufigsten Ursachen — und was du dagegen tust

1. Gegenläufige Zugriffsreihenfolge

Der Vater aller Deadlocks: Prozedur A aktualisiert erst Auftrag, dann Kunde — Prozedur B macht es genau andersherum. Läuft beides parallel oft genug, kracht es zwangsläufig; die Skizze oben zeigt exakt dieses Muster. Die Lösung ist unspektakulär und gerade deshalb so wirksam: eine verbindliche Zugriffsreihenfolge im gesamten Code. Tabellen werden in allen Transaktionen in derselben Reihenfolge angefasst — alphabetisch, nach fachlicher Hierarchie, völlig egal, Hauptsache konsistent. Das ist keine Datenbankeinstellung, sondern eine Code-Konvention. Wenn der Hersteller der Anwendung also sagt, das sei „ein Datenbankproblem“: Der Deadlock-Graph mit den beiden gegenläufigen inputbuf-Blöcken ist dein freundliches Gegenargument.

2. Fehlende Indizes — Scans verbreitern den Kampfplatz

Ein UPDATE mit WHERE-Klausel ohne passenden Index muss die Tabelle scannen — und sperrt dabei weit mehr Zeilen, als es eigentlich ändern will. Je breiter der Scan, desto größer die Wahrscheinlichkeit, dass sich zwei Prozesse in die Quere kommen, die fachlich gar nichts miteinander zu tun haben. Im Deadlock-Graph erkennst du das Muster an Page Locks statt Key Locks und an erstaunlich „unbeteiligten“ Statements. Die Lösung ist ein gezielter Index auf die Filterspalten — danach sperrt das UPDATE nur noch die Zeilen, die es wirklich braucht. Nebenwirkung: Die Query wird auch noch schneller. Es gibt schlechtere Deals.

3. Lock Escalation — aus Nadelstichen wird ein Vorschlaghammer

Hält eine Transaktion zu viele Einzelsperren auf einem Objekt — die Faustregel liegt bei etwa 5.000 —, eskaliert SQL Server auf eine Tabellensperre. Aus chirurgischen Key Locks wird ein Vorschlaghammer, der die komplette Tabelle blockiert, und plötzlich kollidiert jeder mit jedem. Typischer Auslöser sind Massen-Updates und -Deletes ohne Batching: das nächtliche „lösche alles älter als 90 Tage“ in einer einzigen Transaktion. Gegenmittel Nummer eins ist Batching — in Häppchen von ein paar tausend Zeilen arbeiten, zwischendurch committen. ALTER TABLE … SET (LOCK_ESCALATION = DISABLE) existiert auch, kuriert aber nur das Symptom und treibt den Sperren-Speicherverbrauch hoch — Ausnahmewerkzeug, kein Standard.

4. Key-Lookup-Deadlocks — wenn zwei Indizes sich verkeilen

Das subtilste Muster, weil hier ein einzelnes SELECT und ein einzelnes UPDATE auf derselben Tabelle reichen: Das SELECT liest über den Nonclustered Index und springt per Key Lookup in den Clustered Index. Das UPDATE ändert zuerst den Clustered Index und muss dann den Nonclustered Index nachziehen. Zwei Wege durch dieselbe Tabelle, gegenläufige Reihenfolge — Verklemmung. Im Graph verrät sich das Muster dadurch, dass beide Ressourcen Indizes derselben Tabelle sind. Die robusteste Lösung: den Nonclustered Index per INCLUDE um die Spalten erweitern, die das SELECT braucht — als Covering Index entfällt der Lookup, und der zweite Weg verschwindet komplett.

5. Lange Transaktionen und der falsche Isolation Level

Je länger eine Transaktion ihre Sperren hält, desto größer das Zeitfenster für Verklemmungen. Klassiker: Anwendungscode, der mitten in einer offenen Transaktion auf externe Systeme wartet — oder schlimmer, auf Benutzereingaben. Transaktionen gehören kurz und knackig: Daten vorher sammeln, dann öffnen, schreiben, committen. Auf der Sperren-Seite hilft zusätzlich Read Committed Snapshot Isolation (RCSI): Leser arbeiten gegen Zeilenversionen aus der tempdb und blockieren Schreiber nicht mehr — Reader-Writer-Deadlocks verschwinden damit praktisch vollständig. Writer-Writer-Verklemmungen (Ursachen 1 bis 3) löst RCSI dagegen nicht — die zwei gegenläufigen UPDATEs aus der Skizze verkeilen sich auch im Snapshot-Modus.

— Ist RCSI schon aktiv?

SELECT name, is_read_committed_snapshot_on

FROM sys.databases

WHERE name = N'MeineDB';

 

— RCSI aktivieren (braucht kurz exklusiven Zugriff auf die DB)

ALTER DATABASE [MeineDB] SET READ_COMMITTED_SNAPSHOT ON

WITH ROLLBACK IMMEDIATE;

Vor dem Aktivieren zwei Hausaufgaben: Die tempdb muss den Version Store verkraften — wie du sie dafür aufstellst, steht im Konfigurations-Beitrag der GRÜN-Stufe. Und die Anwendung sollte einen kurzen Test durchlaufen, weil sich die Lese-Semantik ändert: Du liest ab sofort den letzten committeten Stand, statt auf laufende Änderungen zu warten. Für 99 Prozent aller Anwendungen ist das genau das, was sie ohnehin erwarten.

Was du auf keinen Fall tun solltest

  • Nicht: NOLOCK über den ganzen Code streuen. Ja, die Deadlocks werden weniger. Dafür liest du ab sofort uncommittete, doppelte oder fehlende Zeilen — Dirty Reads sind kein Theorie-Schreckgespenst, sondern falsche Zahlen im Monatsbericht. Wenn du versionsbasiertes Lesen willst, nimm RCSI, das ist der saubere Weg.
  • Nicht: Retry-Logik als einzige Antwort einbauen. Ein Retry auf 1205 ist sinnvolle Hygiene — als Pflaster. Wer aber eine Welle nur mit Retries zukleistert, verdoppelt die Last, verlängert die Sperrzeiten und macht die Welle größer. Erst Ursache fixen, dann Retry als Sicherheitsnetz behalten.
  • Nicht: DEADLOCK_PRIORITY überall auf HIGH drehen. Wenn alle Priorität haben, hat keiner welche — und der Monitor wählt wieder nach Rollback-Kosten. Priorität ist ein Feinwerkzeug für klar definierte Ausnahmen, etwa Wartungsjobs als designierte Opfer.
  • Nicht: Den Deadlock-Monitor als Feind betrachten. Er ist die Lösung, nicht das Problem. Ohne ihn stünden beide Sessions für immer — der Error 1205 ist die kontrollierte Notlandung, nicht der Absturz.
  • Die drei häufigsten Anfängerfehler

    1. Jeden Deadlock einzeln analysieren statt das Muster der Welle zu suchen. Zwanzig Graphen mit demselben Statement-Paar sind ein Befund — nicht zwanzig Befunde.
    2. NOLOCK als „Performance-Hint“ verteilen und sich später über falsche Berichtszahlen wundern. Dirty Reads sind der teuerste Workaround der SQL-Welt.
    3. Auf Server-Hardware schielen, obwohl der Graph zwei gegenläufige Prozeduren zeigt. Deadlock-Wellen sind fast immer ein Code- oder Index-Thema — mehr CPU macht die Verklemmung nur schneller.

    Nachsorge: Damit es nicht wiederkommt

    Nach der akuten Welle drei strukturelle Maßnahmen: Erstens, die DeadlockCapture-Session dauerhaft laufen lassen — mit File-Target und Rollover kostet sie praktisch nichts und liefert beim nächsten Vorfall die komplette Historie statt der rollierten Reste der system_health. Zweitens, eine Deadlock-Baseline ins Monitoring aufnehmen: Wie viele 1205er pro Tag sind bei euch normal? Ein Anstieg von drei auf dreißig fällt dann auf, bevor der Fachbereich anruft. Drittens, die Zugriffsreihenfolge als Code-Konvention festschreiben und im Review prüfen — die billigste Deadlock-Prävention der Welt steht nicht in der Datenbank, sondern im Entwickler-Wiki. Wo Deadlocks in der Gesamtdiagnose einzuordnen sind, zeigt übrigens das Diagnose-Schema im Beitrag zur GELB-Stufe „SQL Server läuft langsam“.

    Vertiefung in der Buchreihe

    Sperren, Isolation Level und der Version Store füllen in der Buchreihe „SQL Server in der Praxis“ eigene Kapitel — die Übersicht aller Bände findest du auf der SQL-Pillar-Seite unter /sql-server/.

    Empfohlene Bände

    Band 1: Performance & Troubleshooting — Sperr-Architektur im Detail: Lock-Modi, Lock Escalation, Isolation Level, Version Store und die Wait Stats, mit denen du Sperrkonflikte im Gesamtbild erkennst.
    Band 5: SQL Server für Entwickler — Deadlock-arme Code-Muster: Transaktions-Design, Zugriffsreihenfolgen, Batching, saubere Retry-Logik und die ORM-Sünden, die Deadlock-Wellen überhaupt erst auslösen.

    Verwandte Notfälle im Notarztwagen

    Deadlocks kommen selten ohne Begleitsymptome. Diese Beiträge aus dem Cluster lohnen den Blick:

  • Blocking-Kaskaden auflösen (/sql-server-blocking/) — der lineare Bruder des Deadlocks: Wo eine Welle ist, ist meist auch massives Blocking. Head-Blocker finden und gezielt auflösen.
  • SQL Server läuft langsam (/sql-server-langsam/) — das Diagnose-Schema der GELB-Stufe ordnet Sperrkonflikte in die Gesamtdiagnose ein, bevor du dich auf ein Symptom versteifst.
  • CPU dauerhaft bei 100 Prozent (/sql-server-cpu-100-prozent/) — die Scans aus Ursache zwei treiben nicht nur Deadlocks, sondern auch die CPU. Beides zusammen ist ein starkes Index-Indiz.
  • Wait Stats interpretieren (/sql-server-wait-stats/) — LCK_M_*-Wartetypen im Gesamtbild lesen: der DBA-Kompass der GRÜN-Stufe.
  • Drei Wege, wenn die Deadlock-Welle jetzt gerade rollt

    Festpreis-Analyse

    Die Welle kommt jede Nacht wieder, der Hersteller zeigt auf die Datenbank, und intern fehlt die Zeit für die Graph-Archäologie? Dafür gibt es die Festpreis-Analyse: Ich werte die Deadlock-Graphen aus, identifiziere die Muster, prüfe Indizes und Isolation-Einstellungen und liefere einen Bericht mit priorisierten Maßnahmen — inklusive der Argumentationshilfe für das Gespräch mit dem Anwendungshersteller. Zum vereinbarten Festpreis, ohne Stundenzähler.

    Akut-Hotline

    Wenn die Welle gerade jetzt die Produktion lahmlegt: anrufen. Halte den Zugriff auf die system_health-Daten bereit und die Information, was sich zuletzt geändert hat — Release, Datenwachstum, neuer Report. Mit zwei, drei Graphen vor Augen ist das dominante Muster meist in unter einer Stunde identifiziert.

    Selbst-Diagnose-Kit

    Du willst die Welle selbst sezieren? Sehr gut. Das Diagnose-Kit bündelt die Skripte aus diesem Beitrag — system_health-Auswertung, DeadlockCapture-Session, Sperren-Analyse, RCSI-Check — als ausführbares Paket mit Auswertungshilfe und einer Muster-Checkliste für die fünf häufigsten Ursachen.

    Ein letzter Tipp

    Führe das system_health-Skript aus diesem Beitrag einmal auf deinem Produktionsserver aus — heute, ohne akuten Anlass. Die meisten DBAs sind ehrlich überrascht, wie viele Deadlocks ihr Server still und leise wegmoderiert, ohne dass je jemand hingeschaut hat. Drei pro Woche? Alles gut. Dreihundert? Dann hast du gerade eine Welle gefunden, von der nur deine Anwender wussten.

    Häufige Fragen (FAQ)

    Diese Sektion ist auf häufige Suchanfragen abgestimmt. Sie hilft dir, schnell den Punkt zu finden, der dir gerade akut weiterhilft — und sie ist gleichzeitig die Eingabe für das FAQPage-Schema auf der Seite.

    Was ist ein Deadlock im SQL Server?

    Ein Deadlock ist eine zirkuläre Verklemmung: Session A hält eine Sperre und wartet auf eine Ressource, die Session B hält — und B wartet gleichzeitig auf die Ressource von A. Keiner kann weitermachen, keiner gibt freiwillig auf. Der Deadlock-Monitor des SQL Servers erkennt den Kreis, wählt ein Opfer (das mit den geringsten Rollback-Kosten), rollt dessen Transaktion zurück und schickt ihm Error 1205. Der Unterschied zum Blocking: Blocking löst sich von selbst auf, sobald der Blocker fertig ist — ein Deadlock nie. Die saubere Abgrenzung steht im Technik-Abschnitt dieses Beitrags.

    Wie analysiere ich einen Deadlock-Graph?

    Im Graph (XML oder grafisch in SSMS) suchst du drei Dinge: die beteiligten Prozesse mit ihren Statements, die umkämpften Ressourcen (Key Lock, Page Lock, Objekt) und die Pfeilrichtungen — wer hält (Owner), wer wartet (Waiter). Bildet sich ein geschlossener Kreis, hast du die Verklemmung vor Augen. Entscheidend ist dann die Zugriffsreihenfolge: Greifen beide Prozesse auf dieselben Tabellen in umgekehrter Reihenfolge zu? Das ist in der Praxis die häufigste Ursache. Die kommentierte Beispiel-Skizze findest du im Abschnitt zum Diagnose-Pfad.

    Welcher Isolation Level vermeidet Deadlocks?

    Kein Isolation Level eliminiert Deadlocks vollständig — aber Read Committed Snapshot Isolation (RCSI) entschärft die häufigste Klasse: Leser blockieren keine Schreiber mehr und umgekehrt, weil Leser gegen eine Zeilenversion aus dem Version Store lesen. Reader-Writer-Deadlocks verschwinden damit weitgehend. Writer-Writer-Deadlocks bleiben allerdings bestehen — zwei UPDATEs in gegenläufiger Reihenfolge verklemmen sich auch unter RCSI. Höhere Level wie Serializable verschärfen das Problem eher, weil sie mehr und längere Sperren halten. Details und das Aktivierungs-Skript stehen im RCSI-Abschnitt.

    Wie aktiviere ich Deadlock-Logging mit Extended Events?

    Die gute Nachricht: Es läuft schon. Die immer aktive system_health-Session zeichnet jeden Deadlock als xml_deadlock_report auf — du musst die Daten nur abfragen, das Skript dazu steht im Diagnose-Abschnitt dieses Beitrags. Für längere Aufbewahrung oder gezielte Analyse einer Deadlock-Welle lohnt eine eigene XE-Session auf das Event xml_deadlock_report mit File-Target: Die system_health rolliert nämlich, und bei viel Betrieb sind ältere Deadlocks schnell rausgealtert. Trace Flag 1222 ins ERRORLOG geht auch noch, ist aber die Methode von vorgestern.

    Was bedeutet Lock Escalation?

    SQL Server sperrt normalerweise feingranular auf Zeilen- oder Seitenebene. Hält eine Transaktion aber zu viele Einzelsperren (Faustregel: ab etwa 5.000 auf einem Objekt), eskaliert der Server auf eine einzige Tabellensperre — das spart Verwaltungsaufwand, sperrt aber schlagartig die komplette Tabelle. Genau solche Eskalationen verwandeln harmlose Parallelität in Deadlock-Wellen, weil plötzlich jeder mit jedem kollidiert. Typischer Auslöser: Massen-Updates ohne Batching oder Scans wegen fehlender Indizes. Gegenmittel: kleinere Batches, passende Indizes — und nur im begründeten Ausnahmefall ALTER TABLE mit LOCK_ESCALATION = DISABLE.

    Wann sollte ich Read Committed Snapshot Isolation verwenden?

    RCSI ist für die meisten OLTP-Datenbanken eine sinnvolle Standardeinstellung — Azure SQL Database fährt sie ab Werk. Sinnvoll immer dann, wenn Reader-Writer-Konflikte dein Problem sind: Berichte, die Schreiber blockieren, oder Deadlocks zwischen SELECT und UPDATE. Zwei Dinge vorher prüfen: Erstens braucht RCSI Platz im Version Store der tempdb — die muss das verkraften. Zweitens ändert sich die Lese-Semantik: Du liest den letzten committeten Stand statt auf den aktuellen zu warten. Anwendungen, die sich auf Sperr-Verhalten als Logik verlassen (selten, aber es gibt sie), müssen getestet werden.

    Wie verhindere ich Deadlocks zwischen Indizes?

    Der Klassiker ist der Key-Lookup-Deadlock: Ein SELECT liest über den Nonclustered Index und will dann per Lookup in den Clustered Index — während ein UPDATE genau andersherum erst den Clustered Index ändert und dann den Nonclustered Index nachziehen muss. Zwei Wege hinein, gegenläufige Reihenfolge, Verklemmung. Die robusteste Lösung: den Nonclustered Index per INCLUDE zum Covering Index machen, dann entfällt der Lookup komplett. Alternativ entschärft RCSI die Lese-Seite. Wie du das Muster im Deadlock-Graph erkennst, zeigt der Ursachen-Abschnitt dieses Beitrags.