Risolvere gli errori di timeout delle query
Sintomi
Si supponga che un'applicazione eseponga dati da un database di 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. Il tempo disponibile è scaduto prima del completamento dell'operazione o il server non risponde. L'istruzione è stata interrotta.
-
System.Data.SqlClient.SqlException: Timeout expired. Il tempo disponibile è scaduto prima del completamento dell'operazione o il server non risponde.
Spiegazione
Questi errori si verificano sul lato applicazione. L'applicazione imposta un valore di timeout e, se viene raggiunto il timeout, annulla la query. Sul lato SQL Server, un annullamento di query dal lato client causa un evento Attention, 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, è possibile impostare il valore di timeout nella proprietà CommandTimeout.
- Nell'API ODBC viene impostato tramite l'attributo
SQL_ATTR_QUERY_TIMEOUT
nella funzione SQLSetStmtAttr . - Nell'API Java Database Connectivity (JDBC), si usa il metodo setQueryTimeout.
- In OLEDB viene impostata tramite la
DBPROP_COMMANDTIMEOUT
proprietà nellaDBPROP
struttura . - In VBA (Excel), si usa la proprietà ADODB.Command.CommandTimeout.
Il timeout della query è diverso da una proprietà di timeout della connessione. Quest'ultimo controlla il tempo di attesa di una connessione riuscita e non è coinvolto nell'esecuzione della query. Per altre informazioni, vedere Timeout delle query non uguale al timeout della connessione.
Passaggi per la risoluzione dei problemi
Di gran lunga, il motivo più comune per i timeout delle query è l'underperforming 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 è la prima destinazione consigliata per la risoluzione dei problemi. Ecco come controllare 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
sql_batch_completed
eventi estesi erpc_completed
e correlarli nello stessosession_id
oggetto . Se si osserva che un evento completato viene 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:Note
Nell'esempio la
SELECT
query è stata eseguita per quasi 30 secondi e 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) Timestamp: sql_batch_started 54 Selezionare … from Customers WHERE cid = 192937 NULL 2021-09-30 09:50:25.0000 sql_batch_completed 54 Selezionare … from Customers WHERE cid = 192937 29999981 2021-09-30 09:50:55.0000 Attenzione 54 Selezionare … from Customers WHERE cid = 192937 40000 2021-09-30 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
Note
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 da usare le stesse opzioni SET usate in SQLCMD e SSMS. Confrontare le opzioni SET raccogliendo una traccia degli eventi estesi (account di accesso e connessione di eventi con
collect_options_text
) e controllare laoptions_text
colonna . 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 di differenza delle prestazioni delle query tra l'applicazione di database e SSMS.
Controllare se l'impostazione
CommandTimeout
è inferiore alla durata della query prevista. Se l'impostazione dell'utente è corretta e si verificano ancora timeout, è dovuto a 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 della query non corrisponde al timeout della connessione
Un timeout della query è diverso da un timeout della connessione o da un timeout di accesso. Il timeout della connessione o dell'account di 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 di connessione o accesso:
-
Il timeout di connessione è scaduto. Il periodo di timeout è scaduto durante il tentativo di utilizzare il riconoscimento dell'handshake di pre-accesso. Ciò potrebbe verificarsi perché l'handshake di pre-accesso ha avuto esito negativo oppure il server non è stato in grado di rispondere in tempo. Il tempo impiegato nel tentativo di connettersi a questo server era [Pre-Login] initialization=23; handshake=14979;
-
Timeout. Il tempo disponibile è scaduto prima del completamento dell'operazione o il server non risponde. System.ComponentModel.Win32Exception (0x80004005): The wait operation timed out.
Il valore di timeout della connessione è un'impostazione lato client ed è in genere impostata 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 di timeout delle query, guardare questo video.