Résoudre les erreurs d’expiration de la requête
Symptômes
Supposons qu’une application interroge des données à partir d’une base de données SQL Server. Si la requête ne retourne aucune donnée dans le délai d’attente configuré (généralement 30 secondes), l’application annule la requête et génère l’un des messages d’erreur suivants :
-
Délai expiré. Période de délai d’attente écoulée avant l’achèvement de l’opération, ou le serveur ne répond pas. L'instruction a été arrêtée.
-
System.Data.SqlClient.SqlException : Le délai a expiré. Période de délai d’attente écoulée avant l’achèvement de l’opération, ou le serveur ne répond pas.
Explication
Ces erreurs se produisent côté application. L’application définit une valeur de délai d’attente et, si le délai d’attente est atteint, elle annule la requête. Côté SQL Server, une annulation de requête côté client provoque un événement Attention, erreur 3617 (MSSQLSERVER_3617). Si la valeur de délai d’attente côté application est définie sur 0 (sans limite de temps), l’Moteur de base de données exécute la requête jusqu’à ce qu’elle soit terminée.
- dans .NET Framework System.Data.SqlClient, la valeur du délai d’attente est définie sur la propriété CommandTimeout .
- Dans l’API ODBC, elle est définie par le biais de l’attribut
SQL_ATTR_QUERY_TIMEOUT
dans la fonction SQLSetStmtAttr . - Dans l’API Java Database Connectivity (JDBC), elle est définie par le biais de la méthode setQueryTimeout .
- Dans OLEDB, il est défini par le biais de la
DBPROP_COMMANDTIMEOUT
propriété sur laDBPROP
structure. - Dans VBA (Excel), elle est définie via ADODB. Propriété Command.CommandTimeout .
Le délai d’expiration de la requête est différent d’une propriété de délai d’attente de connexion. Ce dernier contrôle le temps d’attente d’une connexion réussie et n’est pas impliqué dans l’exécution de la requête. Pour plus d’informations, consultez Délai d’expiration de la requête qui n’est pas le même que le délai d’expiration de la connexion.
Étapes de dépannage
De loin, la raison la plus courante pour les délais d’attente des requêtes est de sous-former les requêtes. Cela signifie que la requête s’exécute plus longtemps que la valeur de délai d’attente de requête prédéfinie. Accélérer l’exécution de la requête est la première cible recommandée de votre résolution des problèmes. Voici comment vérifier les requêtes :
Utilisez des événements étendus ou une trace SQL pour identifier les requêtes qui provoquent les erreurs de délai d’attente. Vous pouvez tracer l’événement d’attention avec les
sql_batch_completed
événements étendus etrpc_completed
les mettre en corrélation sur le mêmesession_id
. Si vous observez qu’un événement terminé est immédiatement suivi d’un événement d’attention et que la durée de l’événement terminé correspond approximativement au paramètre de délai d’attente, vous avez identifié la requête. Voici un exemple :Note
Dans l’exemple, la
SELECT
requête s’est exécutée pendant presque 30 secondes et s’est arrêtée. L’événement d’attention ayant le même ID de session indique que la requête a été annulée par l’application.Nom Session_id Sql_text Durée (microsecondes) Timestamp sql_batch_started 54 Sélectionner ... from Customers WHERE cid = 192937 NULL 2021-09-30 09:50:25.0000 sql_batch_completed 54 Sélectionner ... from Customers WHERE cid = 192937 29999981 2021-09-30 09:50:55.0000 Attention 54 Sélectionner ... from Customers WHERE cid = 192937 40000 2021-09-30 09:50:55.0400 Exécutez et testez les requêtes dans SQLCMD ou dans SQL Server Management Studio (SSMS).
Si les requêtes sont également lentes dans SQLCMD et SSMS, résolvez et améliorez les performances des requêtes. Pour plus d’informations, consultez Résoudre les problèmes liés aux requêtes en cours d’exécution lente dans SQL Server
Note
Dans SQLCMD et SSMS, la valeur de délai d’attente est définie sur 0 (aucune limite de temps) et les requêtes peuvent être testées et examinées.
Si les requêtes sont rapides dans SQLCMD et SSMS, mais lentes côté application, modifiez les requêtes pour utiliser les mêmes options SET utilisées dans SQLCMD et SSMS. Comparez les options SET en collectant une trace d’événements étendus (connexion et connexion d’événements avec
collect_options_text
) et vérifiez laoptions_text
colonne. Voici un exemple :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))
Pour plus d’informations, consultez Résoudre les problèmes de différence de performances des requêtes entre l’application de base de données et SSMS.
Vérifiez si le
CommandTimeout
paramètre est inférieur à la durée de requête attendue. Si le paramètre de l’utilisateur est correct et que les délais d’attente se produisent toujours, c’est en raison d’un problème de performances de requête. Voici un exemple de code ADO.NET avec une valeur de délai d’attente définie sur 10 secondes :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); } } } } }
Le délai d’attente des requêtes n’est pas le même que le délai d’attente de connexion
Un délai d’attente de requête est différent d’un délai d’expiration de connexion ou d’un délai d’expiration de connexion. La connexion ou le délai d’expiration de connexion se produit lorsque la connexion initiale au serveur de base de données atteint un délai d’attente prédéfini. À ce stade, aucune requête n’a été envoyée au serveur. Ces messages sont des exemples d’erreur de délai d’expiration de connexion ou de connexion :
-
Délai d’expiration de la connexion dépassé Le délai d’attente a expiré lors de la tentative d’utilisation de l’accusé de réception de la négociation de préconnexion. Cela peut être dû au fait que la négociation de préconnexion a échoué, ou que le serveur n’a pas pu répondre à temps. Le temps écoulé lors de la tentative de connexion à ce serveur était de - [Préconnexion] initialisation=23 ; établissement d’une liaison=14979 ;
-
Délai expiré. Période de délai d’attente écoulée avant l’achèvement de l’opération, ou le serveur ne répond pas. System.ComponentModel.Win32Exception (0x80004005) : L’opération d’attente a expiré.
La valeur du délai d’attente de connexion est un paramètre côté client et est généralement définie sur 15 secondes. Pour plus d’informations sur la résolution des problèmes de délai d’attente de connexion, consultez résoudre les problèmes de délai d’expiration de connexion. Pour la résolution des problèmes de délai d’expiration des requêtes, regardez cette vidéo.