Deadlock SELECT / INSERT

10

Diese Instanz hostet die SharePoint 2007-Datenbanken (SP). Wir haben zahlreiche SELECT / INSERT-Deadlocks für eine stark genutzte Tabelle in der SP-Inhaltsdatenbank festgestellt. Ich habe die beteiligten Ressourcen eingegrenzt. Beide Prozesse erfordern Sperren für den nicht gruppierten Index.
Das INSERT benötigt eine IX-Sperre für die SELECT-Ressource und das SELECT benötigt eine S-Sperre für die INSERT-Ressource. Das Deadlock-Diagramm zeigt und drei Ressourcen, 1.) zwei aus dem SELECT (Producer / Consumer Parallel Threads) und 2.) das INSERT.
Ich habe das Deadlock-Diagramm für Ihre Überprüfung angehängt. Da es sich um Microsoft-Code- und -Tabellenstrukturen handelt, können wir keine Änderungen vornehmen.
Ich habe jedoch auf der MSFT SP-Site gelesen, dass empfohlen wird, die Konfigurationsoption auf MAXDOP-Instanzebene auf 1 zu setzen. Da diese Instanz von vielen anderen Datenbanken / Anwendungen gemeinsam genutzt wird, kann diese Einstellung nicht deaktiviert werden.


Daher habe ich beschlossen, zu verhindern, dass diese SELECT-Anweisungen parallel verlaufen. Ich weiß, dass dies keine Lösung ist, sondern eher eine vorübergehende Änderung, um bei der Fehlerbehebung zu helfen. Daher habe ich den „Kostenschwellenwert für Parallelität“ von 25 auf 40 erhöht, obwohl sich die Arbeitslast nicht geändert hat (SELECT / INSERT tritt häufig auf), sind die Deadlocks verschwunden. Meine Frage ist warum?

SPID 356 INSERT verfügt über eine IX-Sperre für eine Seite, die zum nicht gruppierten Index gehört.
SPID 690 SELECT Die Ausführungs-ID 0 verfügt über eine S-Sperre für eine Seite, die zu demselben nicht gruppierten Index gehört

Jetzt

SPID 356 möchte eine IX-Sperre für die SPID 690-Ressource, kann sie jedoch nicht erhalten, da SPID 356 durch die SPID 690-Ausführungs-ID 0 blockiert wird. S-Sperre
SPID 690 Die Ausführungs-ID 1 möchte eine S-Sperre für die SPID 356-Ressource, kann sie jedoch nicht erhalten, da die SPID 690-Ausführungs-ID 1 wird von SPID 356 blockiert und jetzt haben wir unseren Deadlock.

Der Ausführungsplan befindet sich auf meinem SkyDrive

Vollständige Deadlock-Details finden Sie hier

Wenn mir jemand helfen kann zu verstehen, warum ich es wirklich schätzen würde.

EventReceivers-Tabelle.
ID uniqueidentifier no 16
Name nvarchar no 512
SiteId uniqueidentifier no 16
WebId uniqueidentifier no 16
HostId uniqueidentifier no 16
HostType int no 4
ItemId int no 4
DirName nvarchar no 512
LeafName nvarchar no 256
Type int no 4
SequenceNumber int no 4
Assembly nvarchar no 512
Class nvarchar nein 512
Daten nvarchar nein 512
Filter nvarchar nein 512
SourceId tContentTypeId nein 512
SourceType int no 4
Credential int no 4
ContextType varbinary no 16
ContextEventType varbinary no 16
ContextId varbinary no 16
ContextObjectId varbinary no 16
ContextCollectionId varbinary no 16

index_name index_description index_keys
EventReceivers_ByContextCollectionId nicht gruppierten sich auf PRIMARY SITEID, ContextCollectionId
NONCLUSTERED EventReceivers_ByContextObjectId befindet sich auf PRIMARY SITEID, ContextObjectId
EventReceivers_ById Nonclustered, einzigartig gelegen auf PRIMARY SITEID, Id
EventReceivers_ByTarget gruppierten, einzigartig gelegen auf PRIMARY SITEID, webid, HostId, Unterkuntstyp, Typ, ContextCollectionId, ContextObjectId, ContextId, ContextType, ContextEventType, SequenceNumber, Assembly, Klasse
EventReceivers_IdUnique nicht gruppierter, eindeutiger, eindeutiger Schlüssel in der PRIMARY-ID

SQLJarHead
quelle
2
Was tun proc_InsertEventReceiverund proc_InsertContextEventReceivertun, was wir in der XDL nicht sehen können? Um die Parallelität zu verringern, sollten Sie diese Anweisung nicht direkt (mit MAXDOP 1) beeinflussen, anstatt mit serverweiten Einstellungen zu arbeiten.
Aaron Bertrand
1
Ich bin gespannt, wie hoch Ihre MAXDOP-Einstellung ist und wie viele Prozessoren (logisch) Sie haben. SharePoint funktioniert wirklich besser und zieht es vor, auf einem Server mit einem MAXDOP-Server mit einer Breite von 1 zu sein. Ich mag es nicht, aber so haben sie es entwickelt. Können Sie die tatsächlichen Ausführungspläne veröffentlichen? Alles, was ich unter diesem Link sehe, ist die .xdl (Deadlock-Grafik)
Mike Walsh
Hallo meine Herren, ich weiß es wirklich zu schätzen, dass Sie sich die Zeit genommen haben, um zu antworten. Ich werde sowohl die Verfahren als auch die Ausführungspläne für Ihre Überprüfung auf der SkyDrive-Website veröffentlichen. Ich hatte darüber nachgedacht, den Code so zu ändern, dass er die Abfrageoption MAXDOP (1) enthält. Dadurch wird jedoch unsere Unterstützung für Microsoft ungültig. Der physische Server ist eine ProLiant DL580 G4 MAXDOP-Einstellung ist 4 mit insgesamt 8 physischen Prozessoren und H / T ist deaktiviert.
SQLJarHead
Hallo meine Herren, ich habe ein Zip-Paket mit allen Details zum SkyDrive erstellt. Ich habe den Text des ursprünglichen Beitrags so geändert, dass er die URL für das Paket enthält. Bitte sagen Sie mir nicht, wo das Problem liegt, sondern geben Sie mir eine Anleitung und lassen Sie mich dafür arbeiten. HINWEIS: Ich kann keine Codeänderungen oder DDL-Änderungen am zugrunde liegenden Schema vornehmen.
SQLJarHead
1
Sie können den Code also nicht ändern und das Schema nicht ändern. Welche anderen Lösungen erwarten Sie von uns? Wenn Sie für ungültig erklären Microsoft Support besorgt sind, dann bedeutet , dass , dass Sie haben Microsoft Support, in diesem Fall - bei all den Einschränkungen Sie uns gesagt haben , dass Sie nicht tun können - haben Sie darüber nachgedacht ein Support - Ticket mit Microsoft eröffnen?
Aaron Bertrand

Antworten:

14

Auf den ersten Blick sieht dies wie ein klassischer Lookup-Deadlock aus . Die wesentlichen Bestandteile für dieses Deadlock-Muster sind:

  • Eine SELECTAbfrage, die einen nicht abdeckenden nicht gruppierten Index mit einer Schlüsselsuche verwendet
  • Eine INSERTAbfrage, die den Clustered-Index und dann den Nonclustered-Index ändert

Der SELECTgreift zuerst auf den nicht gruppierten Index und dann auf den gruppierten Index zu. Der INSERTZugriff zuerst auf den Clustered-Index, dann auf den Nonclustered-Index. Der Zugriff auf dieselben Ressourcen in einer anderen Reihenfolge, um inkompatible Sperren zu erhalten, ist natürlich eine großartige Möglichkeit, einen Deadlock zu erreichen.

In diesem Fall SELECTlautet die Abfrage:

SELECT-Abfrage

... und die INSERTAbfrage lautet:

INSERT-Abfrage

Beachten Sie die grün hervorgehobene Wartung von nicht gruppierten Indizes.

Wir müssten die serielle Version des SELECTPlans sehen, falls sie sich stark von der parallelen Version unterscheidet. Wie Jonathan Kehayias in seinem Handbuch zur Behandlung von Deadlocks feststellt , ist dieses spezielle Deadlock-Muster sehr empfindlich gegenüber dem Timing und den Details der Implementierung der internen Abfrageausführung. Diese Art von Deadlock kommt und geht oft ohne offensichtlichen externen Grund.

Angesichts des Zugriffs auf das betreffende System und geeigneter Berechtigungen können wir sicher genau herausfinden, warum der Deadlock beim parallelen Plan auftritt, nicht jedoch bei der seriellen (unter Annahme derselben allgemeinen Form). Potenzielle Untersuchungslinien umfassen für optimierte verschachtelten Schleifen überprüft und / oder Prefetching - von denen beide intern kann die Isolationsstufe eskalieren zu REPEATABLE READfür die Dauer der Anweisung. Es ist auch möglich, dass eine Funktion der Zuweisung des parallelen Index-Suchbereichs zu dem Problem beiträgt. Wenn der Serienplan verfügbar wird, werde ich möglicherweise einige Zeit damit verbringen, die Details weiter zu untersuchen, da dies möglicherweise interessant ist.

Die übliche Lösung für diese Art von Deadlocking besteht darin, den Index abzudecken, obwohl die Anzahl der Spalten in diesem Fall dies möglicherweise unpraktisch macht (und außerdem sollten wir uns in SharePoint nicht mit solchen Dingen herumschlagen, wurde mir gesagt). Letztendlich gibt es die Empfehlung für Nur-Serien-Pläne bei der Verwendung von SharePoint aus einem bestimmten Grund (wenn auch nicht unbedingt gut, wenn es darauf ankommt). Wenn die Änderung der Kostenschwelle für Parallelität das Problem im Moment behebt, ist dies gut. Längerfristig würde ich wahrscheinlich versuchen, die Workloads zu trennen, möglicherweise mithilfe von Resource Governor, damit interne SharePoint-Abfragen das gewünschte MAXDOP 1Verhalten erhalten und die andere Anwendung Parallelität verwenden kann.

Die Frage des Austauschs in der Sackgasse scheint mir ein roter Hering zu sein; einfach eine Folge der unabhängigen Threads, die Ressourcen besitzen, die technisch im Baum erscheinen müssen. Ich kann nichts sehen, was darauf hindeutet, dass die Börsen selbst direkt zum Deadlocking-Problem beitragen.

Paul White 9
quelle
6

Wenn dies ein klassischer Such-Deadlock war , enthält die Ressourcenliste sowohl den Clustered Index als auch den Non-Clustered Index. Normalerweise hält der SELECT eine SHARED-Sperre für den NC-Index und wartet auf eine SHARED-Sperre für das CI, während der INSERT eine EXCLUSIVE-Sperre für das CI erhält und auf eine EXCLUSIVE-Sperre für den NC wartet. In der Ressourcenliste in der Deadlock-XML werden in diesem Fall beide Objekte aufgelistet.

Da das Deadlock-Diagramm nur den NC-Index enthält, können wir diese Option ausschließen.

Wenn dies aufgrund von Nested Loop Join mit UNORDERED PREFETCH eine Dead Lock war , gibt der Ausführungsplan an, ob der UNORDERED PREFETCH-Algorithmus verwendet wird, was auch hier nicht der Fall ist (siehe Update unten).

Das lässt uns annehmen, dass dies aufgrund des Parallelplans ein Deadlock ist.

Das Deadlock-Diagramm wird nicht richtig gerendert. Wenn Sie sich jedoch das Deadlock-XML ansehen, sehen Sie, dass zwei Threads aus der SELECT-Anweisung (SPID 690) am Deadlock beteiligt sind. Der Consumer-Thread hält eine SHARED-Sperre auf SEITE 1219645 und wartet auf den Produzenten auf Port801f8ed0 (e_waitPipeGetRow). Der Producer-Thread wartet auf eine gemeinsame Sperre auf SEITE 1155940.

Die INSERT-Anweisung hält eine IX-Sperre auf SEITE 1155940 und wartet auf eine IX-Sperre auf SEITE 1219645, was zu einem Deadlock führt.

Ich glaube, dass ein Deadlock verhindert wird, wenn ein serieller Plan für die SELECT-Anweisung verwendet wird, da zu keinem Zeitpunkt eine SHARED-Sperre für mehr als eine Seite erforderlich ist. Ich denke auch, dass der serielle Plan fast der gleiche sein wird wie der parallele Plan (ohne Parallelitätsoperator).

[AKTUALISIERT basierend auf Pauls Kommentar]

Anscheinend verwendet der Plan einen OPTIMIZED Nested Loop-Algorithmus

Dies erklärt, warum die SHARED-Sperren bis zum Ende der Anweisung gehalten werden. WIEDERHOLBARES LESEN in Kombination mit einem parallelen Plan ist anfälliger für Deadlocks als ein serieller Plan, da der parallele Plan Sperren aus verschiedenen Bereichen eines Index erfassen und beibehalten kann, während der serielle Plan Sperren auf sequentiellere Weise erfasst.

Roji P Thomas
quelle
Einverstanden. Wenn dieser Deadlock mit einem tatsächlichen LOOKUP zusammenhängt, hätte die Warte-Ressource für SELECT auf den Clustered-Index verwiesen. Ich konnte dies ausschließen, indem ich den Seitenkopf für jede Warte-Ressource (SPID 690 Wait Resource = PAGE: 1155940 | SPID 356 Wait Resource = PAGE 1219645) über DBCC PAGE anzeigte. Beide befanden sich in der Index-ID 5 (IndexID 5 = EventReceivers_ByContextObjectId). Dies zeigt auf den NC-Index in der angegebenen Tabelle (EventReceivers).
SQLJarHead
Meine Herren, nochmals vielen Dank, dass Sie sich die Zeit genommen haben, dieses interessante Problem zu analysieren. Einige Fragen: 1.) Roji weist darauf hin, dass die parallele SPID mehr als eine Seite anfordert. Ich sehe das in keinem der Hinrichtungspläne. Betrachtet man die Anzahl der Zeilen, so verarbeitet für den Operator INDEX SEEK nur ein Thread der beiden Hersteller Zeilen. Wie haben Sie festgestellt, dass mehr als eine Seite angefordert wurde? (1/2)
SQLJarHead
2.) Setzt ein OPTIMIZED Nested Loop-Algorithmus die Isolationsstufe immer auf REAPTABLE READ? Ich habe die XML-Ausgabe der Ausführungspläne überprüft und sehe nur einen Lesevorgang für die SPID-Verbindung. Ich gehe davon aus, dass dies nur auf der Ebene des Planbetreibers aufgerufen wird. (2/2)
SQLJarHead
Das Sperrverhalten von OPTIMIZED Nested Loops ist vergleichbar mit REPEATABLE READ (behält die Sperren bis zum Ende der Anweisung bei ), setzt jedoch nicht explizit die Isolationsstufe der Transaktion auf REPEATABLE READ. Ich denke, das beantwortet auch Ihre Frage. Es ist nicht so, dass die parallelen Threads mehr als eine Seite gleichzeitig anfordern, aber ein paralleler Thread hält eine Sperre auf einer Seite und ein anderer Thread wartet auf eine Sperre auf einer anderen Seite
Roji P Thomas