Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Warum blockiert diese SQL Server-Abfrage?

  • Prozess 9196a8 hat Seite 151867 Slot 174 im X-Modus und will Seite 140302 Slot 31 im S-Modus
  • Prozess 88b5b8 hat Seite 140302 Slot 31 im X-Modus und will Seite 151867 Slot 174 im S-Modus
  • die beiden Löschungen laufen unter isolationlevel="repeatable read (3)"

Der Deadlock tritt also auf dem Basisheap der Tabelle auf (RID-Sperren anstelle von Schlüsselsperren implizieren einen Heap, keinen Btree). Die hohe Isolationsstufe (wahrscheinlich verursacht durch DTC, nach dem xact-Namen zu urteilen) macht die RCSI-Einstellung irrelevant.

Welchen Typ haben die Spalten PARTYEXTERNALREF und PARTYTYPE? Die übergebenen Parameter sind NVARCHAR (d. h. Unicode) und wenn die Spalten VARCHAR (d. h. Ascii) sind, dann aufgrund der Regeln von Priorität der Datentypen der NC-Index würde nicht verwendet werden. Aufgrund des damit verbundenen Tabellenscans und der verwendeten hohen Isolationsstufe ist ein Deadlock fast unvermeidlich.

Die Lösung wäre die Verwendung von Parametern vom Typ VARCHAR für @P0 und @P1, sodass der NC-Index genutzt würde, um den Tabellenscan zu vermeiden.

Wenn die Parameter bereits vom Typ VARCHAR sind und Sie anhand des Ausführungsplans bestätigen können, dass eine Suche auf dem NC verwendet wird, wäre meine erste Frage, was sonst macht die Transaktion außer den Löschanweisungen?

Übrigens geben Sie nur den Namen des NC-Index an, aber ich nehme an, er ist auf (PARTYEXTERNALREF, ISCOUNTERPARTY, PARTYID) .

Aktualisieren

Da Ihr Kommentar sagt, dass die Spalten sind NVARCHAR dann ist die Tabellen-Scan-Hypothese wahrscheinlich falsch. Es gibt drei weitere Möglichkeiten, einen Deadlock zu verursachen, die untersucht werden müssen:

  • jede andere Anweisung, die von der Transaktion vor dem DELETE ausgeführt wird (dies ist am wahrscheinlichsten)
  • jegliche Überschneidung in den Zeilen, die durch zwei DELETE-Anweisungen ausgewählt wurden, die am Deadlock beteiligt waren
  • Hash-Kollision

Nur für die ersten beiden Hypothesen können Sie jetzt alles tun (untersuchen Sie, ob sie richtig sind). Für das letzte kann ich Ihnen sagen, wie Sie es überprüfen können, aber es ist nicht trivial. Es ist unwahrscheinlich und etwas schwierig zu beweisen, aber es ist möglich. Da Sie von einem Deadlock-Fall (dem angehängten XML) wissen, verwenden Sie ihn als Untersuchungsbasis:

  • Stellen Sie eine Point-in-Time-Kopie der Datenbank mit Stopp bei wieder her 2011-09-02T19:00:29.690
  • führen Sie DBCC TRACEON(3604,-1) aus
  • unter Verwendung von DBCC PAGE (<restored db id>, 1, 151867, 3) Überprüfen Sie die Werte in Steckplatz 174
  • unter Verwendung von DBCC PAGE(, 1, 140302, 3)` die Werte in Steckplatz 31 überprüfen
  • führen Sie SELECT %%lockres%% FROM PARTIES WHERE PARTYEXTERNALREF = ... AND ISCOUNTERPARTY='N' and PARTYID=... aus und übergebe die oben gelesenen Werte
  • vergleicht die resultierenden Lock-Hash-Werte, wenn sie übereinstimmen, dann haben Sie eine Hash-Kollision und dies hat den Deadlock verursacht.