Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Obtention occasionnelle de SqlException :le délai d'attente a expiré

Vous devez étudier cela côté serveur pour comprendre pourquoi le délai d'exécution expire. Notez que le serveur n'a pas de délai d'attente, le délai d'attente est causé par la valeur par défaut de 30 secondes sur SqlCommand.CommandTimeout .

Une bonne ressource est attentes et files d'attente , qui est une méthodologie pour diagnostiquer les goulots d'étranglement des performances avec SQL Server. En fonction de la cause réelle du délai d'attente, des mesures appropriées peuvent être prises. Vous devez établir avant tout si vous avez affaire à une exécution lente (un mauvais plan) ou à un blocage.

Si je devais deviner, je dirais que le modèle malsain de IF EXISTS... UPDATE est la cause première. Ce modèle est incorrect et entraînera des échecs en cas de concurrence. Deux transactions simultanées exécutant le IF EXISTS arriveront simultanément à la même conclusion et les deux essayer d'INSERT ou UPDATE . Selon les contraintes existantes dans la base de données, vous pouvez vous retrouver avec un blocage (le cas chanceux) ou avec une écriture perdue (le cas malchanceux). Cependant, seule une enquête appropriée révélerait la cause profonde réelle. Pourrait être quelque chose de totalement différent, comme événements de croissance automatique .

Votre procédure gère également de manière incorrecte le bloc CATCH. Vous devez toujours vérifiez le XACT_STATE() car la transaction peut déjà être annulée au moment où votre bloc CATCH s'exécute. Ce que vous attendez de nommer la transaction n'est pas non plus clair, c'est une erreur courante que je vois souvent associée à la confusion des transactions nommées avec des points de sauvegarde. Pour un modèle correct, voir Gestion des exceptions et transactions imbriquées .

Modifier

Voici une manière possible d'étudier cela :

  1. Modifier le CommandTimeout à 0 (c'est-à-dire infini).
  2. Activer le blocked process threshold , réglez-le sur 30 secondes (l'ancien CommandTimeout)
  3. Surveiller dans le profileur pour Événement de rapport de processus bloqué
  4. Démarrez votre charge de travail
  5. Vérifiez si le profileur génère des événements de rapport. Si c'est le cas, ils en identifieront la cause.

Ces actions provoqueront un événement "rapport de processus bloqué" chaque fois que vous auriez eu un délai d'attente, si le délai d'attente était dû à un blocage. Votre application continuera d'attendre que le blocage soit supprimé, si le blocage est causé par un verrouillage en direct alors il attendra pour toujours.