Ich habe zwei Datensätze mit minimaler Protokollierung in eine leere Heap-Tabelle eingefügt, indem ich zwei parallel und mit SQL der folgenden Form ausgeführte SQL-Aufgaben ausgeführt habe.
INSERT INTO Table (TABLOCK) SELECT FROM ...
Nachdem der Job etwas hängen geblieben war, wurde eine der SQL-Aufgaben zum Deadlock-Opfer. Unten finden Sie eine XML-Ausgabe des Deadlock-Diagramms.
Kann jemand erklären, was unter der Haube geschah?
<resource-list>
<objectlock lockPartition="0" objid="1586156746" subresource="FULL" dbid="7" objectname="dbo.TargetTable" id="lock7374a00" mode="IX" associatedObjectId="1586156746">
<owner-list>
<owner id="process9609dc8" mode="Sch-S"/>
<owner id="process9609dc8" mode="IX"/>
</owner-list>
<waiter-list>
<waiter id="process5e13048" mode="X" requestType="convert"/>
</waiter-list>
</objectlock>
<objectlock lockPartition="0" objid="1586156746" subresource="FULL" dbid="7" objectname="dbo.TargetTable" id="lock7374a00" mode="IX" associatedObjectId="1586156746">
<owner-list>
<owner id="process5e13048" mode="Sch-S"/>
<owner id="process5e13048" mode="IX"/>
</owner-list>
<waiter-list>
<waiter id="process9609dc8" mode="X" requestType="convert"/>
</waiter-list>
</objectlock>
</resource-list>
Die Dinge werden viel schwieriger, weil ich festgestellt habe, dass die beiden Execute SQL-Aufgaben in den meisten Fällen erfolgreich parallel ausgeführt werden können. Versuchen Sie es unten:
Create table dbo.TablockInsert (c1 int, c2 int, c3 int)
--then issue the script in two Execute Sql Task in parallel you won't fail:
insert into dbo.TablockInsert(TABLOCK) SELECT 1, 1, 1
Da der einzige Unterschied die Anweisung SELECT ... FROM ... ist, kann die Anweisung SELECT ... FROM ... hier einen Einfluss auf den Sperrmodus haben?
Antworten:
Das Data Loading Performance Guide wurde für SQL Server 2008 geschrieben, aber soweit ich das beurteilen kann, hat Microsoft in diesem Bereich keine Verbesserungen für Heaps vorgenommen. Hier ist ein Angebot für Ihr Ladeszenario:
Der wichtige Teil ist, dass Sie keine BU-Sperre erhalten
INSERT ... SELECT
. Sie erhalten immer eine exklusive Sperre für den Tisch, sodass jeweils nur eine ausgeführt werdenINSERT
kann.In den Kommentaren haben Sie angegeben, dass Sie 100.000 Zeilen oder weniger einfügen und dass während der Einfügungen keine anderen Prozesse in den Tabellen ausgeführt werden. Wenn ich zwei INSERT-Abfragen an die Datenbank sende, würde ich eines von drei Dingen erwarten:
In allen Fällen profitieren Sie entweder davon oder werden nicht verletzt, wenn Sie
TABLOCKX
der Abfrage einen Hinweis hinzufügen. Dies ist meine Empfehlung, den Deadlock zu umgehen. Wenn Sie wissen möchten, warum der Deadlock manchmal auftritt, müssen Sie nach einer anderen Antwort suchen.In einem anderen Szenario, in dem Sie wirklich eine parallele Einfügung benötigen, können Sie das BU-Problem auf zwei Arten umgehen, indem Sie Ihren Heap partitionieren und jede Sitzung in eine separate Partition einfügen oder Ihre Daten über BCP, BULK INSERT oder Integration Services laden .
quelle
Sie einfügen in
dbo.TargetTable
zwei Sitzungen und beide mitTABLOCK
hint.Bothprocess9609dc8
undprocess5e13048
ProzesshalteSch-S
undIX
Schlösser , die miteinander kompatibel sind , so dass beide Verfahren gleichzeitig aufnehmen kann. Aber beide wollenIX
Sperre inExclusive X
Typ konvertieren .X
Schlösser sind nicht miteinander kompatibel. Daher hat SQL Server eine der Sitzungen als Deadlock-Opfer ausgewählt, anstatt unendlich aufeinander zu warten.Grundlegende Deadlocking-Informationen.
Diagramm zur Sperrkompatibilität (Database Engine).
Deadlocks erkennen und beenden.
quelle