Risolvere gli errori di timeout della query
Sintomi
Si supponga che un'applicazione esegua una query dei dati da un database SQL Server. Se la query non restituisce dati entro il valore di timeout configurato (in genere 30 secondi), l'applicazione annulla la query e genera uno di questi messaggi di errore:
-
Timeout scaduto. È trascorso il periodo di timeout prima del completamento dell'operazione oppure il server non risponde. L'istruzione è stata terminata.
-
System.Data.SqlClient.SqlException: timeout scaduto È trascorso il periodo di timeout prima del completamento dell'operazione oppure il server non risponde.
Spiegazione
Questi errori si verificano sul lato dell'applicazione. L'applicazione imposta un valore di timeout e, se questo viene raggiunto, annulla la query. Sul lato SQL Server, un annullamento della query dal lato client causa un evento di attenzione, errore 3617 (MSSQLSERVER_3617). Se il valore di timeout sul lato applicazione è impostato su 0 (nessun limite di tempo), il motore di database esegue la query fino al completamento.
- In .NET Framework System.Data.SqlClient il valore di timeout viene impostato sulla proprietà CommandTimeout.
- Nell'API ODBC viene impostato tramite l'attributo
SQL_ATTR_QUERY_TIMEOUT
nella funzione SQLSetStmtAttr. - Nell'API JDBC (Java Database Connectivity) viene impostato tramite il metodo setQueryTimeout.
- In OLEDB viene impostato tramite la proprietà
DBPROP_COMMANDTIMEOUT
nella strutturaDBPROP
. - In VBA (Excel) viene impostato tramite la proprietà ADODB.Command.CommandTimeout.
Il timeout delle query è diverso da una proprietà di timeout della connessione. Quest'ultimo controlla il tempo di attesa per una connessione riuscita e non è coinvolto nell'esecuzione di query. Per altre informazioni, vedere Differenza tra timeout della query e timeout della connessione.
Procedura di risoluzione dei problemi
Di gran lunga, il motivo più comune per i timeout delle query è la scarsa prestazione delle query. Ciò significa che la query viene eseguita più a lungo del valore di timeout della query predefinito. Rendere più veloce l'esecuzione della query è il primo obiettivo consigliato per la risoluzione dei problemi. Di seguito è indicato come verificare le query:
Usare eventi estesi o traccia SQL per identificare le query che causano gli errori di timeout. È possibile tracciare l'evento di attenzione insieme agli eventi estesi
sql_batch_completed
erpc_completed
, e correlarli sullo stessosession_id
. Se si osserva che un evento completato è immediatamente seguito da un evento di attenzione e la durata dell'evento completato corrisponde approssimativamente all'impostazione di timeout, la query è stata identificata. Ecco un esempio:Nota
Nell'esempio, la query
SELECT
è stata eseguita per quasi 30 secondi esatti ed è stata arrestata. L'evento di attenzione con lo stesso ID sessione indica che la query è stata annullata dall'applicazione.Nome Session_id Sql_text Durata (microsecondi) Data e ora sql_batch_started 54 Selezionare … from Customers WHERE cid = 192937 NULL 30/09/2021 09:50:25.0000 sql_batch_completed 54 Selezionare … from Customers WHERE cid = 192937 29999981 30/09/2021 09:50:55.0000 Attenzione 54 Selezionare … from Customers WHERE cid = 192937 40000 30/09/2021 09:50:55.0400 Eseguire e testare le query in SQLCMD o in SQL Server Management Studio (SSMS).
Se le query sono lente anche in SQLCMD e SSMS, risolvere i problemi e migliorare le prestazioni delle query. Per informazioni dettagliate, vedere Risolvere i problemi relativi alle query a esecuzione lenta in SQL Server
Nota
In SQLCMD e SSMS il valore di timeout è impostato su 0 (nessun limite di tempo) e le query possono essere testate e analizzate.
Se le query sono veloci in SQLCMD e SSMS, ma sono lente sul lato applicazione, modificare le query in modo che utilizzino le stesse opzioni SET usate in SQLCMD e SSMS. Confrontare le opzioni SET raccogliendo una traccia eventi estesi (account di accesso e connessione degli eventi con
collect_options_text
) e controllando la colonnaoptions_text
. Ecco un esempio: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))
Per altre informazioni, vedere Risolvere i problemi relativi alle differenze di prestazioni delle query tra l'applicazione di database e SSMS.
Controllare se l'impostazione
CommandTimeout
è inferiore alla durata prevista della query. Se l'impostazione dell'utente è corretta e si verificano ancora timeout, è a causa di un problema di prestazioni delle query. Ecco un esempio di codice ADO.NET con un valore di timeout impostato su 10 secondi: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); } } } } }
Il timeout delle query non corrisponde al timeout della connessione
Il timeout di una query è diverso da un timeout di connessione o da un timeout di accesso. Il timeout della connessione o dell'accesso si verifica quando la connessione iniziale al server di database raggiunge un periodo di timeout predefinito. In questa fase non è stata inviata alcuna query al server. Questi messaggi sono esempi di errore di timeout della connessione o dell'accesso:
-
Timeout di connessione scaduto. Il periodo di timeout è scaduto durante il tentativo di utilizzare il riconoscimento dell'handshake di pre-accesso. Questo problema può essere dovuto al fatto che l'handshake di pre-accesso non è riuscito oppure il server non è riuscito a rispondere nel tempo. La durata del tentativo di connessione a questo server è stata [Pre-Login] inizializzazione=23; handshake=14979;
-
Timeout scaduto. È trascorso il periodo di timeout prima del completamento dell'operazione oppure il server non risponde. System.ComponentModel.Win32Exception (0x80004005): Tempo di attesa scaduto.
Il valore di timeout della connessione è un'impostazione lato client ed è in genere impostato su 15 secondi. Per altre informazioni su come risolvere i problemi di timeout della connessione, vedere Risolvere i problemi di timeout della connessione. Per la risoluzione dei problemi relativi al timeout delle query, guardare questo video.