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

SQL-Deadlock mit Auswahl-/Aktualisierungsvorgängen für eine Tabelle

Die beiden Abfragen, die den Deadlock verursachen, sind SELECT unten (process id="process3980de4558" ):

select @existing = team_it_cube_attr_05 from tbl_Ref_Attr_Prod_Team where prod_id = @rec_key

Und das UPDATE Abfrage unten (process id="process386ed48188" ):

UPDATE D
SET D.team_rss_attr_01 = LEFT(S.mkt_prodchar_13,25)...

Die <resource-list> Abschnitt notiert das SELECT Die Abfrage besaß eine exklusive (X) Sperre auf einer Seite und versuchte, eine Intent-Shared (IS)-Sperre auf einer anderen Seite zu erwerben, während sie Daten las. Das UPDATE Die Abfrage besaß bereits eine IS-Sperre und versuchte, eine X-Sperre auf einer Seite zu erwerben, um die Aktualisierung durchzuführen.

Angesichts der Verknüpfung mit dieser Tabelle:

...from tbl_Ref_Attr_Prod_Team where prod_id = @rec_key...
...INNER JOIN tbl_Ref_Attr_Prod_Team D ON D.prod_key=P.prod_key...

Die SELECT Abfrage besitzt bereits eine exklusive Sperre. Dies bedeutet wahrscheinlich, dass es Teil einer größeren Transaktion ist, die bereits ein UPDATE durchgeführt hat in einer vorherigen Abfrage. Sperren von früheren Abfragen werden beibehalten, um die Datenintegrität während der Transaktion zu bewahren (abhängig von Transaktionsisolationsstufe ).

Das UPDATE Abfrage muss die Tabelle tbl_Ref_Attr_Prod_team lesen . Es erwirbt beim Lesen von Daten Intent-Shared-Locks auf Seiten und Zeilen. Wenn das UPDATE Abfrage die übereinstimmenden Zeilen findet, wird sie versuchen, die IS-Sperren in X-Sperren umzuwandeln. IS-Sperren sind nicht mit X-Sperren kompatibel. Da die SELECT Abfrage hat bereits eine IS-Sperre auf einer oder mehreren dieser Seiten, die Abfragen blockieren sich gegenseitig.

Eine mögliche Ursache wären fehlende Indexe auf tbl_Ref_Attr_Prod_team.prod_key . Ohne einen Index für diese Spalte wird das UPDATE Die Abfrage scannt alle Zeilen in der Tabelle tbl_Ref_Attr_Prod_team .

Auch wenn ein Index auf prod_key existiert , wenn die Tabelle eine kleine Anzahl von Zeilen enthält, entscheidet SQL Server möglicherweise, dass die Leistung besser wäre, wenn die Abfrage die gesamte Tabelle scannen würde, anstatt den Index zu suchen. Das Aufzeichnen des Abfrageplans beim Auftreten des Deadlocks würde diese Theorie bestätigen.

Wir stoßen regelmäßig auf kleine Tabellen-Deadlocks, wenn wir neue Datenbanken bereitstellen. Anfangs sind die Tabellen winzig, und Tabellenscans verursachen alle Arten von Deadlocks. Später, wenn die Tabellen größer sind, übersteigen die berechneten Kosten für das Scannen der Tabelle die Kosten für das Suchen des Index, und die Deadlocks treten nicht mehr auf. In Testumgebungen, in denen die Anzahl der Zeilen immer kleiner wird, haben wir auf die Verwendung von FORESEEK zurückgegriffen und WITH INDEX Hinweise zum Erzwingen von Indexsuchen anstelle von Scans. Wir freuen uns darauf, Abfragepläne über die Abfragespeicherfunktion von SQL Server 2016 erzwingen zu können.