Problembehandlung bei Abfragetimeoutfehlern

Problembeschreibung

Angenommen, eine Anwendung fragt Daten aus einer SQL Server-Datenbank ab. Wenn die Abfrage keine Daten innerhalb des konfigurierten Timeoutwerts zurückgibt (in der Regel 30 Sekunden), bricht die Anwendung die Abfrage ab und generiert eine der folgenden Fehlermeldungen:

  • Das Timeout ist abgelaufen. The timeout period elapsed prior to completion of the operation or the server is not responding. Die Anweisung wurde beendet.

  • System.Data.SqlClient.SqlException: Timeout abgelaufen. The timeout period elapsed prior to completion of the operation or the server is not responding.

Erklärung

Diese Fehler treten auf der Anwendungsseite auf. Die Anwendung legt einen Timeoutwert fest, und wenn das Timeout erreicht ist, wird die Abfrage abgebrochen. Auf der SQL Server-Seite verursacht ein clientseitiger Abfrageabbruch ein Aufmerksamkeitsereignis, Fehler 3617 (MSSQLSERVER_3617). Wenn der Timeoutwert auf der Anwendungsseite auf 0 (kein Zeitlimit) festgelegt ist, führt Datenbank-Engine die Abfrage aus, bis sie abgeschlossen ist.

  • In System.Data.SqlClient von .NET Framework wird der Timeoutwert uber die Eigenschaft CommandTimeout festgelegt.
  • In der ODBC-API wird er über das Attribut SQL_ATTR_QUERY_TIMEOUT in der Funktion SQLSetStmtAttr festgelegt.
  • In der JDBC-API (Java Database Connectivity) wird er über die Methode setQueryTimeout festgelegt.
  • In OLEDB wird er über die Eigenschaft DBPROP_COMMANDTIMEOUT in der DBPROP-Struktur festgelegt.
  • In VBA (Excel) wird er über die Eigenschaft ADODB.Command.CommandTimeout festgelegt.

Das Abfragetimeout unterscheidet sich von der Eigenschaft Verbindungstimeout. Letzteres steuert, wie lange auf eine erfolgreiche Verbindung gewartet wird, und ist nicht an der Abfrageausführung beteiligt. Weitere Informationen finden Sie unter Abfragetimeout ist nicht identisch mit Verbindungstimeout.

Schritte zur Problembehandlung

Der bei weitem häufigste Grund für Abfragetimeouts ist eine unzureichende Leistung der Abfragen. Dies bedeutet, dass die Abfrage länger ausgeführt wird als der vordefinierte Abfragetimeoutwert. Das empfohlene vorrangige Ziel bei der Fehlerbehebung ist es, die Abfrage schneller laufen zu lassen. Hier erfahren Sie, wie Sie Abfragen überprüfen:

  1. Verwenden Sie erweiterte Ereignisse oder die SQL-Ablaufverfolgung, um die Abfragen zu identifizieren, die die Timeoutfehler verursachen. Sie können das Aufmerksamkeitsereignis zusammen mit den erweiterten sql_batch_completed- und rpc_completed-Ereignissen nachverfolgen und auf demselben session_id korrelieren. Wenn Sie feststellen, dass auf ein abgeschlossenes Ereignis unmittelbar ein Aufmerksamkeitsereignis folgt und die Dauer des abgeschlossenen Ereignisses ungefähr der Timeouteinstellung entspricht, haben Sie die Abfrage identifiziert. Hier ist ein Beispiel:

    Hinweis

    In diesem Beispiel wurde die Abfrage SELECT fast genau 30 Sekunden lang ausgeführt und dann beendet. Das Aufmerksamkeitsereignis mit derselben Sitzungs-ID zeigt, dass die Abfrage durch die Anwendung abgebrochen wurde.

    Name Session_id Sql_text Dauer (Mikrosekunden) Zeitstempel
    sql_batch_started 54 Wählen Sie ... from Customers WHERE cid = 192937 NULL 30.09.2021 09:50:25.0000
    sql_batch_completed 54 Wählen Sie ... from Customers WHERE cid = 192937 29999981 30.09.2021 09:50:55.0000
    Achtung 54 Wählen Sie ... from Customers WHERE cid = 192937 40000 30.09.2021 09:50:55.0400
  2. Ausführen und Testen der Abfragen in SQLCMD oder in SQL Server Management Studio (SSMS).

  3. Wenn die Abfragen auch in SQLCMD und SSMS langsam sind, sollten Sie Probleme der Abfragen beheben und deren Leistung verbessern. Ausführliche Informationen finden Sie unter Problembehandlung bei langsam ausgeführten Abfragen in SQL Server

    Hinweis

    In SQLCMD und SSMS wird der Timeoutwert auf 0 (kein Zeitlimit) festgelegt, und die Abfragen können getestet und untersucht werden.

  4. Wenn die Abfragen in SQLCMD und SSMS schnell, aber anwendungsseitig langsam sind, ändern Sie die Abfragen so, dass dieselben SET-Optionen verwendet werden, die in SQLCMD und SSMS verwendet werden. Vergleichen Sie die SET-Optionen, indem Sie eine Ablaufverfolgung für erweiterte Ereignisse (Anmelde- und Verbindungsereignisse mit collect_options_text) sammeln und die Spalte options_text überprüfen. Hier ist ein Beispiel:

    ALTER EVENT SESSION [setOptions] ON SERVER 
    ADD EVENT sqlserver.existing_connection(SET collect_options_text=(1) 
        ACTION(package0.event_sequence,package0.last_error,sqlos.system_thread_id,sqlserver.context_info,sqlserver.session_id,sqlserver.sql_text)), 
    ADD EVENT sqlserver.login(SET collect_options_text=(1)
        ACTION(sqlos.system_thread_id,sqlserver.context_info,sqlserver.sql_text))
    

    Weitere Informationen finden Sie unter Problembehandlung bei Abfrageleistungsunterschieden zwischen Datenbankanwendung und SSMS.

  5. Überprüfen Sie, ob die Einstellung CommandTimeout kleiner als die erwartete Abfragedauer ist. Wenn die Einstellung des Benutzers korrekt ist und dennoch Timeouts auftreten, liegt dies an einem Problem bei der Abfrageleistung. Hier ist ein ADO.NET-Codebeispiel mit einem Timeoutwert, der auf 10 Sekunden festgelegt ist:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Data.SqlClient;
    using System.Data;
    
    namespace ConsoleApplication6
    {
        class Program
        {
            static void Main()
            {
                string ConnectionString = "Data Source=.\sql2019;Integrated Security=SSPI;Initial Catalog=tempdb;";
                string queryString = "exec test";
    
                using (SqlConnection connection = new SqlConnection(ConnectionString))
                {
                    connection.Open();
                    SqlCommand command = new SqlCommand(queryString, connection);
    
                    // Setting command timeout to 10 seconds
                    command.CommandTimeout = 10;
                    //command.ExecuteNonQuery();
                    try {
                        command.ExecuteNonQuery();
                    }
                    catch (SqlException e) {
                        Console.WriteLine("Got expected SqlException due to command timeout ");
                        Console.WriteLine(e);
                    }
                }
            }
        }
    }
    

Das Abfragetimeout entspricht nicht dem Verbindungstimeout.

Ein Abfragetimeout unterscheidet sich von einem Verbindungstimeout oder einem Anmeldetimeout. Ein Verbindungs- oder Anmeldetimeout tritt auf, wenn die erste Verbindung mit dem Datenbankserver einen vordefinierten Timeout-Zeitraum erreicht. Bis zu diesem Zeitpunkt wurde keine Abfrage an den Server gesendet. Diese Meldungen sind Beispiele für Einen Verbindungs- oder Anmeldetimeoutfehler:

  • Verbindungstimeout abgelaufen Der Timeoutzeitraum, der beim Versuch verstrichen ist, die Handshake-Bestätigung vor der Anmeldung zu erhalten. Dies kann darauf zurückzuführen sein, dass der Handshake vor der Anmeldung fehlgeschlagen ist oder der Server nicht rechtzeitig reagieren konnte. Die Dauer, die beim Versuch, eine Verbindung mit diesem Server herzustellen, aufgewendet wurde, war [Pre-Login] initialization=23; handshake=14979;

  • Das Timeout ist abgelaufen. The timeout period elapsed prior to completion of the operation or the server is not responding. System.ComponentModel.Win32Exception (0x80004005): Timeout des Wartezeitvorgangs.

Der Wert für das Verbindungstimeout ist eine clientseitige Einstellung, die in der Regel bei 15 Sekunden liegt. Weitere Informationen zum Beheben von Verbindungstimeouts finden Sie unter Problembehandlung bei Verbindungstimeouts. Informationen zur Problembehandlung bei Abfragetimeouts finden Sie in diesem Video.