Marks Antwort erweitern ...
Wenn ein Client-Timeout-Ereignis auftritt (z. B. .net CommandTimeout), sendet der Client ein "ABORT" an SQL Server. SQL Server gibt dann einfach die Abfrageverarbeitung auf. Es wird keine Transaktion zurückgesetzt, es werden keine Sperren freigegeben.
Jetzt wird die Verbindung an den Verbindungspool zurückgegeben, sodass sie auf SQL Server nicht geschlossen wird. Sollte dies jemals passieren (über KILL oder Client-Neustart usw.), werden die Transaktionen + Sperren gelöscht. Beachten Sie, dass sp_reset_connection sie nicht löscht oder nicht löscht, obwohl dies angekündigt wird
Dieser Abfall aus dem Abbruch blockiert andere Prozesse.
Um SQL Server Transaktionen + Sperren für das Client-Timeout (ausschließlich ABORT-Ereignisse) zu löschen, verwenden Sie SET XACT_ABORT ON.
Sie können überprüfen, ob dies 2 Abfragefenster in SSMS öffnet:
Fenster 1:
Stellen Sie im Menü Query..Query Options ein Timeout von 5 Sekunden ein und führen Sie dieses aus
BEGIN TRAN
UPDATE sometable WITH (TABLOCKX) SET foo = foo WHERE 1 = 0;
WAITFOR DELAY '00:00:10' -- just has to be longer then timeout
Fenster 2, dies wird für immer warten (oder Ihre Zeitüberschreitung treffen)
SELECT * FROM sometable
SET XACT_ABORT ON hat auch interessante Nebenwirkungen:
- @@ TRANCOUNT wird beim impliziten Rollback auf Null gesetzt, aber der Fehler 266 wird unterdrückt (dies geschieht, wenn @@ TRANCOUNT beim Ein- und Ausstieg aus einem gespeicherten Prozess unterschiedlich ist).
- XACT_STATE wird -1 sein (es ist "zum Scheitern verurteilt")
Die Kombination davon bedeutet, dass Sie SAVEPOINTS nicht für teilweise Commits / Rollbacks verwenden können (obwohl ich mich nicht an das genaue Verhalten erinnern kann). Welches passt zu mir
SO-Links zu SET XACT_ABORT:
Auf verschachtelten gespeicherten Prozessen:
Bei sp_reset_connection:
Ich beantworte dies mit Zögern, da Ihre Beschreibung des Problems nicht genügend Informationen enthält, um 100% sicher zu sein, dass dies der beste Rat ist. "Hängt oder löst eine Ausnahme aus" weist darauf hin, dass die Ursache des Problems nicht richtig verstanden wurde. Gehen Sie daher vorsichtig vor.
Die einfachste Lösung hierfür ist wahrscheinlich
SET XACT_ABORT ON
.XACT_ABORT
legt fest, ob SQL Server im Falle eines Laufzeitfehlers eine Transaktion zurücksetzt. Die Standardeinstellung setztSET XACT_ABORT OFF
nur die Anweisung zurück, die einen Fehler verursacht hat, und lässt alle übergeordneten Transaktionen offen.Der Nebeneffekt "gotcha" der Standardeinstellung ist, dass ein Timeout genau das gleiche Problem verursachen kann, eine offene Transaktion, für deren Bearbeitung und Rollback der Kunde verantwortlich ist. Wenn der Kunde nicht versucht / fängt / zurückrollt, bleibt die Transaktion offen, bis die Ultra-Gewalt von (und ich zitiere @gbn) behandelt wird
KILL <spid>
.Die oft zitierten Artikel von Erland Sommarskog zur Fehlerbehandlung in SQL Server enthalten alle Hintergrundinformationen und Strategien, die Sie für den Umgang mit diesen Szenarien und mehr benötigen.
Bearbeiten (folgender Kommentar): Um offene Transaktionen zu identifizieren, ist sp_whoisactive wahrscheinlich die vollständigste Funktion.
quelle