Ich habe ein Deadlock-Diagramm von einem Deadlock, bei dem ein Prozess ein SELECT und einer ein UPDATE ausführt. Dies scheint der klassische Fall zu sein, in dem SELECT eine NCI-Sperre erhält, um einen Join durchzuführen, und dann eine CI-Sperre, um alle Daten durch Nachschlagen abzurufen. Das UPDATE verwendet die CI-Sperre, um eine Aktualisierung durchzuführen, und muss dann eine NCI sperren, da die Aktualisierung zu einer Statusänderung führt und die NCI das Auffinden von Elementen nach Status erleichtert.
Das Problem ist, dass sich eine der Sperren, die das UPDATE wünscht, NICHT in der Tabelle befindet, die aktualisiert wird, und ich kann nicht herausfinden, warum dies geschieht.
Hier ist die AUSWAHL:
SELECT *,
RIGHT(c.CC_NUMBER, 4) AS CC_LAST_4,
DATEDIFF(ss, '1970-01-01', plan_started ) plan_started_epoch,
DATEDIFF(ss, '1970-01-01', plan_expires ) plan_expires_epoch
FROM customers c, accounts a, parent_cos pc, htt_customers_overlay_ultra u
WHERE c.customer_id = a.customer_id
AND u.customer_id = c.customer_id
AND a.cos_id=pc.cos_id
AND u.customer_id = 9300;
Hier ist das UPDATE:
UPDATE htt_customers_overlay_ultra SET plan_state = 'Active' WHERE customer_id = 9300;
Gemäß dem Deadlock-Diagramm erhält das UPDATE jedoch eine Sperre für ACCOUNTS.ACCOUNT0, die PK (CI) der Tabelle ACCOUNTS. Die Overlay-Tabelle enthält keine Fremdschlüssel. Es gibt einige Standardeinschränkungen, für die ich derzeit keine Berechtigung habe.
Ich habe mir das Deadlock-Diagramm in SSMS und in SQL Sentry Plan Explorer Pro angesehen und bin nicht klüger.
Hier sind die Ausführungspläne:
Ich möchte herausfinden, warum es diese Sperre erhält, und dann den besten Weg, um diese Anrufe zu serialisieren.
Dinge, die mir bekannt sind und die ich dem Kunden bereits mitgeteilt habe, die sich auf die genommenen Schlösser auswirken, aber nicht erklären, welche scheinbar nicht verwandte Schlösser entstehen:
Entfernen Sie * und identifizieren Sie die benötigten Spalten und ändern Sie die NCIs, um sie abzudecken. Dies würde möglicherweise dazu führen, dass SELECT weniger Sperren verwendet
Stellen Sie fest, warum das System dieselben Daten auswählt, die von einem anderen Prozess verarbeitet werden. Dies würde möglicherweise die beiden Prozesse verringern, die gleichzeitig ausgeführt werden
In SELECT befindet sich ein Tabellenscan
quelle
X
Tastensperre für "dbo.ACCOUNTS" von einer früheren Anweisung in derselben Transaktion erhalten haben, die in der Grafik nicht dargestellt ist?SELECT
hatU
der PK-Index eine Sperre vonhtt_customers_overlay_ultra
- warum? Für diesen Prozess wird 0 Protokoll verwendet.process589f948
) hat eineU
Sperre und versucht, es in eineX
Sperre umzuwandeln , wird aber durch eineS
Sperre blockiert , die vonSELECT
(process5240988
) gehalten wirdread_committed_snapshot
.Antworten:
Die
UPDATE
Abfrage hat eineX
Sperre für einen Schlüssel in "dbo.ACCOUNTS", die verhindert,SELECT
dass eineS
Sperre abgerufen wird .Die
SELECT
Abfrage hat eineS
Sperre für einen Schlüssel vonhtt_customers_overlay_ultra
. DieUPDATE
Abfrage hat eineU
Sperre für denselben Schlüssel und wird beim Versuch, diese in eineX
Sperre umzuwandeln, blockiert .Der Ausführungsplan für das ist
UPDATE
überhaupt nicht verfügbar,Accounts
daher gibt es keinen offensichtlichen Grund dafür, dass eine Schlüsselsperre aktiviert istAccounts
. Die Update-Transaktion startet0.01
Sekunden vor dem Batch.2013-01-13 08:49:30.213
vs2013-01-13 08:49:30.223
.Möglicherweise gab es eine vorhergehende Anweisung in einem anderen Stapel (daher im Deadlock-Diagramm nicht dargestellt), die die Transaktion tatsächlich gestartet und die mysteriöse
X
Sperre erworben hat.quelle
UPDATE
tohtt_customers_overlay_ultra
zuvorAccounts
in derselben Transaktion aktualisiert worden wäre, würde es dies natürlich erklären (obwohl es ein nicht aktualisierendes Update sein müsste, da das verwendete Protokoll = 0 ist) oder möglicherweise einSELECT
mit einem explizitenXLOCK
Hinweis.trancount="2"
. Ich glaube, es bedeutet, dass es 2 gabbegin transaction
... Das kann wiederum erklären, warum Dump nicht hatupdate accounts
...@@trancount = 2
esbegin tran
irgendwo explizit AFAIK geben muss .