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: