SQL Server-Transaktionszeitlimit

9

Gibt es in SQL Server 2008 R2 eine Möglichkeit, ein Zeitlimit für eine Datenbankänderung mit einer Transaktion zu verursachen? Wir haben ein Szenario, in dem unser Anwendungscode eine Ausnahme hängt oder auslöst und kein Rollback oder Commit ausführt. Dies führt dann dazu, dass andere Sitzungen hängen bleiben und auf den Abschluss der Transaktion warten.

David Gray Wright
quelle

Antworten:

20

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:

gbn
quelle
Die Zukunft sagt hallo! "Beachten Sie, dass sp_reset_connection sie nicht löscht oder nicht löscht, obwohl dies angekündigt wird" - Ich glaube nicht, dass dies in aktuellen Versionen von SQL Server mehr zutrifft.
Kamilk
11

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_ABORTlegt fest, ob SQL Server im Falle eines Laufzeitfehlers eine Transaktion zurücksetzt. Die Standardeinstellung setzt SET XACT_ABORT OFFnur 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.

Mark Storey-Smith
quelle
Ich habe mit etwas Googeln Möglichkeiten gefunden, offene Transaktionen zu finden, wenn der Hang auftritt - vielleicht ist dies die beste Lösung. Das heißt, um herauszufinden, was die nicht geschlossene Transaktion im Code verursacht, und um die Lücken im Code zu beheben. Als Referenz für andere. DBCC OPENTRAN gibt die älteste aktive Transaktion zurück -> msdn.microsoft.com/en-us/library/ms182792.aspx Oder etwas Ähnliches? -> weblogs.sqlteam.com/mladenp/archive/2008/04/29/…
David Gray Wright
Ich habe immer gedacht, Erland würde dem SET XACT_ABORT nicht gerecht sommarskog.se/error-handling-I.html#XACT_ABORT
gbn