Deadlock beim Löschen der Anweisung

11

Ich bekomme einen Deadlock, wenn ein SQL Server-Job ausgeführt wird. Der Deadlock tritt bei einer einfachen DELETE-Anweisung auf. Ich hätte gedacht, dass eine SELECT / UPDATE-Abfrage ausgeführt werden muss, um den Deadlock zu verursachen. Aber es sieht so aus, als wäre es DELETE / DELETE Deadlock ...

Was ich suche, ist, warum ich einen DELETE / DELETE-Deadlock bekomme. Es wird (meines Wissens) verschiedene Parameter übergeben.

Irgendwelche Ideen? Vielen Dank.

deadlock-list
2014-05-20 07:30:09.66 spid25s      deadlock victim=process409048
2014-05-20 07:30:09.66 spid25s       process-list
2014-05-20 07:30:09.66 spid25s        process id=process409048 taskpriority=0 logused=0 waitresource=PAGE: 12:1:7127294 waittime=4352 ownerId=629860973 transactionname=DELETE lasttranstarted=2014-05-20T07:30:05.307 XDES=0x397219620 lockMode=U schedulerid=5 kpid=3792 status=suspended spid=150 sbid=0 ecid=3 priority=0 trancount=0 lastbatchstarted=2014-05-20T07:30:05.307 lastbatchcompleted=2014-05-20T07:30:05.307 clientapp=QSQL25 hostname=MORRIS hostpid=1528 isolationlevel=read committed (2) xactid=629860973 currentdb=12 lockTimeout=4294967295 clientoption1=671088672 clientoption2=128056
2014-05-20 07:30:09.66 spid25s         executionStack
2014-05-20 07:30:09.66 spid25s          frame procname=adhoc line=1 stmtstart=68 sqlhandle=0x020000000b887a18f75d0aa07c25a9b8630fca696aa0e5d2
2014-05-20 07:30:09.66 spid25s     DELETE FROM dbo.UserDetailsData WHERE        (Username = @P1) AND (UserDate = @P2)     
2014-05-20 07:30:09.66 spid25s          frame procname=unknown line=1 sqlhandle=0x000000000000000000000000000000000000000000000000
2014-05-20 07:30:09.66 spid25s     unknown     
2014-05-20 07:30:09.66 spid25s         inputbuf
2014-05-20 07:30:09.66 spid25s        process id=process432e08 taskpriority=0 logused=0 waitresource=PAGE: 12:1:7127916 waittime=2648 ownerId=629859744 transactionname=DELETE lasttranstarted=2014-05-20T07:30:04.833 XDES=0x4c3426b50 lockMode=U schedulerid=6 kpid=5988 status=suspended spid=146 sbid=0 ecid=3 priority=0 trancount=0 lastbatchstarted=2014-05-20T07:30:04.833 lastbatchcompleted=2014-05-20T07:30:04.820 clientapp=QSQL25 hostname=MORRIS hostpid=1528 isolationlevel=read committed (2) xactid=629859744 currentdb=12 lockTimeout=4294967295 clientoption1=671088672 clientoption2=128056
2014-05-20 07:30:09.66 spid25s         executionStack
2014-05-20 07:30:09.66 spid25s          frame procname=adhoc line=1 stmtstart=68 sqlhandle=0x020000000b887a18f75d0aa07c25a9b8630fca696aa0e5d2
2014-05-20 07:30:09.66 spid25s     DELETE FROM dbo.UserDetailsData WHERE        (Username = @P1) AND (UserDate = @P2)     
2014-05-20 07:30:09.66 spid25s          frame procname=unknown line=1 sqlhandle=0x000000000000000000000000000000000000000000000000
2014-05-20 07:30:09.66 spid25s     unknown     
2014-05-20 07:30:09.66 spid25s         inputbuf
2014-05-20 07:30:09.66 spid25s        process id=process39ea562c8 taskpriority=0 logused=0 waitresource=PAGE: 12:1:7127916 waittime=4352 ownerId=629860973 transactionname=DELETE lasttranstarted=2014-05-20T07:30:05.307 XDES=0x13e0e4b50 lockMode=U schedulerid=2 kpid=7124 status=suspended spid=150 sbid=0 ecid=1 priority=0 trancount=0 lastbatchstarted=2014-05-20T07:30:05.307 lastbatchcompleted=2014-05-20T07:30:05.307 clientapp=QSQL25 hostname=MORRIS hostpid=1528 isolationlevel=read committed (2) xactid=629860973 currentdb=12 lockTimeout=4294967295 clientoption1=671088672 clientoption2=128056
2014-05-20 07:30:09.66 spid25s         executionStack
2014-05-20 07:30:09.66 spid25s          frame procname=adhoc line=1 stmtstart=68 sqlhandle=0x020000000b887a18f75d0aa07c25a9b8630fca696aa0e5d2
K09
quelle
5
Nein, in anderen Szenarien außerhalb von SELECT / UPDATE kann ein Deadlock auftreten. Alles, was Sie wirklich brauchen, sind zwei Prozesse, die jeweils eine Ressource benötigen, die der andere hält. (1) Sind die DELETE-Anweisungen Teil einer größeren Transaktion? (2) Können Sie das Deadlock-XML anstelle des beschissenen Fehlerprotokolltextes irgendwo veröffentlichen?
Aaron Bertrand
Könnten Sie bitte das Tabellenschema der dbo.UserDetailsDataEinbeziehung aller Indizes veröffentlichen? Wissen Sie auch, ob diese Anweisungen mit denselben Parametern aufgerufen werden? Angesichts der Tatsache, dass für beide kein Protokoll verwendet wird, frage ich mich, ob Sie die Anrufe nur serialisieren müssen, weil sie aufeinander treten.
Jon Seigel
Wie bekomme ich das XML? Ich habe den Fehler aus den SQL Server-Fehlerprotokollen erhalten. Anweisungen werden mit unterschiedlichen Parametern aufgerufen. Wir haben kürzlich eine Reihe von gefilterten Indizes hinzugefügt, die nach UserDate-Feldern filtern.
K09
Fangen Sie das Deadlock-Diagrammereignis im Profiler ab. Nachdem Sie es abgefangen haben, klicken Sie mit der rechten Maustaste auf die Zeile -> extrahieren Sie Ereignisdaten -> speichern Sie sie irgendwo als .xdl und veröffentlichen Sie ihren Inhalt (es ist eine XML) auf Pastebin (oder einem ähnlichen Ort).
Marian
1
Hallo, XML hier gepostet ... hoffe das hilft! dl.dropboxusercontent.com/u/16953128/DeadlockTest.xdl
K09

Antworten:

14

Was ich suche, ist, warum ich einen DELETE / DELETE-Deadlock bekomme.

Es scheint, dass der Deadlock auftritt, weil:

  1. spid 54 ecid 0erwirbt eine update ( U) - SeitensperrePAGE: 12:1:5147422
  2. spid 166 ecid 3fordert eine update ( U) - Seitensperre auf derselben Seite an und wird blockiert
  3. spid 54 ecid 2fordert eine update ( U) - Seitensperre auf derselben Seite an ...

Für die Abfrage werden Seiten vorab abgerufen, wobei Aktualisierungssperren von erworben werden ecid 0. Das ist Schritt 1 oben. In Schritt 3 ecid 2fordert ein untergeordneter Thread derselben parallelen Abfrage ( ) dieselbe Sperre an. Normalerweise wäre dies kein Problem. SQL Server kennt ecid 0und ecid 2ist Threads desselben übergeordneten Prozesses. Leider steht Schritt 2 dem im Weg und es kommt zu einem Deadlock.

Das heißt, Sie sollten sich nicht wirklich darum kümmern, warum der Deadlock auftritt. Die wichtige Frage ist, wie Sie ihn vermeiden können. Die Antwort ist, einen effizienten Zugriffspfad für die bereitzustellen DELETE. Die Anweisung muss Zeilen finden WHERE Username = @P1 AND UserDate = @P2, daher sollten Sie einen Index für diese Spalten haben.

Und natürlich haben Sie einen solchen Index. Die eigentliche Frage ist, warum Ihre Probleme aufgetreten sind, nachdem Sie gefilterte Indizes hinzugefügt haben.

Die Antwort darauf ist, dass zusätzliche Spalteninformationen erforderlich sind, um die zu löschenden gefilterten Indexzeilen zu lokalisieren (und ihre Prädikate zu überprüfen). Wenn die Abfrage einen schmalen Ausführungsplan / pro Zeile verwendet , kann die Ausführungsengine die zusätzlichen Spalten im Operator "Clustered Index Delete" nicht wie in einem breiten / pro Index-Plan abrufen.

Weitere Details dazu und ein Beispiel finden Sie in diesem Blogbeitrag .

In diesem Fall müssen die Spalteninformationen aus dem Teil des Plans rechts neben "Clustered Index Delete" stammen. Daher wird ein paralleler Clustered Index-Scan verwendet, und Sie erhalten eine langsame Abfrage mit hohem Deadlock-Potenzial.

Die Antwort lautet: Führen Sie einen der folgenden Schritte aus:

  1. Entfernen Sie die gefilterten Indizes
  2. Fügen Sie gefilterte Indexschlüssel- / Include- / Prädikatspalten zum vorhandenen Namens- / Datumsindex hinzu
  3. Erzwingen Sie einen umfassenden Aktualisierungsplan (dies wird nicht unterstützt )
  4. Führen Sie die Abfrage unter Snapshot-Isolation aus (nicht RCSI).

Option 2 wäre meine starke Präferenz.

Option 4 (danke Jack Douglas) hat den Vorteil, Deadlocks zu entfernen und sollte angesichts der disjunkten Natur der Änderungen keine "Aktualisierungskonflikte" verursachen. Es ist jedoch erforderlich, die Snapshot-Isolation auf Datenbankebene zu aktivieren und die Isolationsstufe explizit zu ändern. und wird das zugrunde liegende Problem nicht beheben : Sie werden immer noch mit einem verschwenderischen parallelen Tabellenscan enden, bei dem eine nette Indexsuche das ist, was Sie wirklich wollen.

Paul White 9
quelle