ProgrammationDéveloppeur Backend

Comment mettre en œuvre un traitement des erreurs efficace et une journalisation en SQL au niveau des procédures stockées, afin de détecter et d'analyser les pannes lors de l'exécution de la logique métier ?

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse.

Le traitement des erreurs et l'organisation de la journalisation en SQL ont acquis une popularité particulière avec le développement de processus métier complexes, lorsque il est devenu important non seulement d'arrêter l'exécution en cas d'erreur, mais aussi de consigner le fait d'un échec et, si possible, de continuer à travailler. À l'origine, SQL ne possédait pas de mécanismes avancés de try-catch, et chaque SGBD proposait ses propres mécanismes.

Historique de la question :

Les premières versions des normes SQL n'avaient pas d'opérateurs intégrés pour capturer les erreurs dans les procédures. Plus tard, les fabricants ont commencé à mettre en œuvre des constructions telles que TRY...CATCH dans Microsoft SQL Server ou HANDLER dans MySQL, permettant un contrôle plus flexible du flux de travail directement au niveau de la base de données.

Problème :

Les erreurs peuvent survenir en raison de données incorrectes ou pour des raisons systémiques. Si la procédure stockée n'implémente pas la capture et l'enregistrement des erreurs, le débogage et la maintenance deviennent extrêmement difficiles. De plus, il est nécessaire de pouvoir distinguer les erreurs critiques des erreurs gérées, afin de ne pas interrompre l'exécution des opérations métier là où cela n'est pas nécessaire.

Solution :

Dans les systèmes modernes, il est conseillé d'implémenter des constructions de collecte et de journalisation des erreurs. Il faut créer des tables de journalisation séparées, utiliser TRY...CATCH (SQL Server) ou DECLARE ... HANDLER (MySQL), conserver des informations détaillées sur les exceptions afin d'analyser ensuite les causes des pannes.

Exemple de code (SQL Server) :

CREATE PROCEDURE dbo.UpdateCustomer @CustomerID INT, @NewName NVARCHAR(100) AS BEGIN BEGIN TRY UPDATE Customers SET Name = @NewName WHERE CustomerID = @CustomerID; END TRY BEGIN CATCH INSERT INTO ErrorLog (ErrorMessage, ErrorSeverity, ErrorTime) VALUES (ERROR_MESSAGE(), ERROR_SEVERITY(), GETDATE()); THROW; END CATCH END;

Caractéristiques clés :

  • L'utilisation de TRY...CATCH permet d'isoler le code potentiellement dangereux.
  • L'insertion des erreurs dans la table de journalisation avec un maximum de détails.
  • Throw/Error raising pour une bonne terminaison de la procédure et la transmission des informations à la couche appelante.

Questions pièges.

Tous les types d'erreurs peuvent-ils être capturés à l'intérieur du bloc TRY...CATCH (ou via un handler) ?

Non, toutes les erreurs, par exemple, les pannes graves du serveur, ne peuvent pas être interceptées. Les erreurs de type "Attention," ou l'échec de la connexion échappent au traitement transactionnel.

Que se passera-t-il avec les modifications non validées dans la procédure en cas d'erreur, si aucune transaction n’est utilisée ?

Les modifications seront partiellement validées, une partie des mises à jour sera intégrée à la base, et une partie pourrait être perdue. Pour éviter une incohérence, il est recommandé d'utiliser toujours des transactions.

BEGIN TRY BEGIN TRANSACTION; --...code COMMIT; END TRY BEGIN CATCH ROLLBACK; END CATCH

Peut-on utiliser INSERT EXEC directement depuis le bloc CATCH pour enregistrer une erreur à partir d'un autre contexte ?

Pas toujours : INSERT EXEC est interdit dans certains contextes (par exemple, s'il y a déjà une transaction active), ce qui peut entraîner des erreurs de second niveau. Il est préférable de collecter les détails de l'erreur localement et de les enregistrer ensuite via un INSERT unique.

Erreurs typiques et anti-modèles

  • Absence de journalisation des erreurs.
  • Ignorer TRANSACTION, ce qui entraîne la rupture des données.
  • Journalisation uniquement de textes, sans codes d'erreur ni temps/code utilisateur.

Exemple pratique

Cas négatif

Le client a implémenté la logique uniquement via RAISERROR sans journalisation, donc les erreurs n'étaient pas conservées ni analysées.

Avantages :

  • Moins de code.

Inconvénients :

  • Impossible de comprendre les causes des pannes ; impossible d'analyser les problèmes en production.

Cas positif

Utilisation de TRY...CATCH plus la table ErrorLog, consignation de l'heure, du code d'erreur, de l'utilisateur, du texte et de la trace.

Avantages :

  • Analyse des erreurs facile.
  • Localisation rapide des problèmes.
  • Transparence pour les analystes métiers.

Inconvénients :

  • Nécessite de maintenir les journaux, parfois de les nettoyer pour les optimiser.