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

Gelegentlich SqlException:Timeout abgelaufen

Sie müssen dies auf der Serverseite untersuchen, um zu verstehen, warum die Ausführung eine Zeitüberschreitung aufweist. Beachten Sie, dass der Server kein Timeout hat, das Timeout wird durch die standardmäßigen 30 Sekunden auf SqlCommand.CommandTimeout .

Eine gute Ressource ist Wartezeiten und Warteschlangen , eine Methode zum Diagnostizieren von Leistungsengpässen mit SQL Server. Basierend auf der tatsächlichen Ursache der Zeitüberschreitung können geeignete Maßnahmen ergriffen werden. Sie müssen in erster Linie feststellen, ob Sie es mit einer langsamen Ausführung (einem schlechten Plan) oder einer Blockierung zu tun haben.

Wenn ich eine Vermutung wagen würde, würde ich sagen, dass das ungesunde Muster von IF EXISTS... UPDATE ist die eigentliche Ursache. Dieses Muster ist falsch und führt zu Fehlern unter Parallelität. Zwei gleichzeitige Transaktionen, die IF EXISTS ausführen gleichzeitig werden beide zum gleichen Schluss kommen und beide versuchen Sie INSERT oder UPDATE . Abhängig von den bestehenden Einschränkungen in der Datenbank kann es zu einem Deadlock (der glückliche Fall) oder zu einem verlorenen Schreibvorgang (der unglückliche Fall) kommen. Allerdings würde nur eine ordnungsgemäße Untersuchung die eigentliche Ursache aufdecken. Könnte etwas ganz anderes sein, wie automatische Wachstumsereignisse .

Ihre Prozedur behandelt auch den CATCH-Block falsch. Sie müssen immer Überprüfen Sie den XACT_STATE() da die Transaktion möglicherweise bereits zurückgesetzt wurde, wenn Ihr CATCH-Block ausgeführt wird. Es ist auch nicht klar, was Sie von der Benennung der Transaktion erwarten. Dies ist ein häufiger Fehler, den ich häufig sehe, wenn benannte Transaktionen mit Sicherungspunkten verwechselt werden. Ein korrektes Muster finden Sie unter Ausnahmebehandlung und verschachtelte Transaktionen .

Bearbeiten

Hier ist eine Möglichkeit, dies zu untersuchen:

  1. Ändern Sie den relevanten CommandTimeout auf 0 (dh unendlich).
  2. Aktivieren Sie den blocked process threshold , setzen Sie es auf 30 Sekunden (das frühere CommandTimeout)
  3. Überwachen Sie im Profiler das Berichtsereignis für blockierte Prozesse
  4. Starten Sie Ihr Arbeitspensum
  5. Prüfen Sie, ob der Profiler Berichtsereignisse erstellt. Wenn dies der Fall ist, werden sie die Ursache lokalisieren.

Diese Aktionen verursachen jedes Mal ein Ereignis „Bericht über blockierten Prozess“, wenn Sie eine Zeitüberschreitung erhalten hätten, wenn die Zeitüberschreitung durch Blockierung verursacht wurde. Ihre Anwendung wird weiterhin warten, bis die Blockierung aufgehoben wird, wenn die Blockierung durch ein Live-Sperre dann wird es ewig warten.