it-swarm-fr.com

Quelle est la meilleure méthode pour ajouter une manipulation des erreurs dans les Procs stockés SQL 2005?

Qu'est-ce qui est un bon moyen de faire des processus stockus suffisamment robustes pour qu'ils puissent s'ajouter très bien et contenir une manipulation des erreurs?

En outre, quelle est la meilleure façon de gérer plusieurs scénarios d'erreur dans un processus stocké et d'avoir un système de rétroaction intelligent qui permettra d'obtenir des informations d'erreur significatives aux applications d'appel?

11
kacalapy

Alex Kuznetsov a un bon chapitre de son livre Programmation de la base de données défensive (Chapitre 8) (chapitre 8) qui couvre T-SQL Essayez ... Catch, T-SQL Transactions et Définissez XACT_ABORT Paramètres et utiliser la manipulation des erreurs côté client. Cela vous aidera beaucoup à décider laquelle des options constitue le plus de sens pour ce que vous devez accomplir.

Il est disponible pour gratuit AT ( Ce site . Je ne suis en aucun cas affilié à la société, mais je possède la version papier de ce livre.

Il y a beaucoup de détails sur ce sujet qui sont très bien expliqués par Alex.

par demande de Nick ... (mais tout cela n'est pas dans le chapitre)

En termes de mise à l'échelle, vous devez être brutalement honnête sur lesquels les activités doivent être dans le code DB et qui devraient être dans l'application. Avez-vous déjà remarqué comment le code d'exécution rapide a tendance à revenir à la conception d'une seule préoccupation par méthode?

Le moyen le plus simple de communiquer serait des codes d'erreur personnalisés (> 50 000). C'est aussi assez rapide. Cela signifie que vous devez conserver le code DB et le code de l'application en synchronisation. Avec un code d'erreur personnalisé, vous pouvez également renvoyer des informations utiles dans la chaîne de message d'erreur. Comme vous avez un code d'erreur strictement pour cette situation, vous pouvez écrire un analyseur dans le code d'application adapté au format de données de l'erreur.

De plus, quelles conditions d'erreur nécessitent une nouvelle logique dans la base de données? Si vous souhaitez réessayer après X secondes, vous feriez mieux de manipuler cela dans le code de l'application afin que la transaction ne bloque pas autant. Si vous ne soumettez pas de nouveau à nouveau une opération DML immédiatement, répétez-la dans le SP pourriez être plus efficace. N'oubliez pas que vous devrez éventuellement dupliquer un code ou ajouter un couche de SPS pour accomplir une nouvelle tentative.

Vraiment, c'est actuellement la plus grande douleur avec essayer ... Catch Logic dans SQL Server pour le moment. Cela peut être fait, mais c'est un peu d'une OAF. Recherchez quelques améliorations qui arrivent à cela dans SQL Server 2012, notamment exceptions du système de reconstitution (préservant le numéro d'erreur d'origine). De plus, il y a FORMATMESSAGE , qui ajoute une certaine flexibilité dans la construction de messages d'erreur, en particulier à des fins de journalisation.

12
Phil Helmer

Ceci est notre modèle (enregistrement d'erreur supprimé)

Remarques:

  • Sans Xact_Abort, tous les TXN commencent et commettent/Rollbacks doivent être jumelés
  • Un commit des décréments @@ Trancount
  • Un retour retour @@ TranCount à zéro pour que vous obtiendriez une erreur 266
  • Vous ne pouvez pas renverser la couche actuelle uniquement (par exemple, décrément @@ Trancount sur Rollback)
  • Xact_abort supprime l'erreur 266
  • Chaque processus stocké doit être conforme au même modèle afin que chaque appel soit atomique
  • La vérification de la restauration est réellement redondante à cause de xact_abort. Cependant, cela me fait sentir mieux, a l'air étrange sans, et permet des situations où vous ne le voulez pas sur
  • Cela permet à la clientèle client txns (comme Linq)
  • Remus Rusan a une coquille similaire qui utilise des points de sauvegarde. Je préfère un appel db atomique et n'utilisez pas de mises à jour partielles comme leur article

... alors ne créez pas plus de txns que nécessaire

Pourtant,

CREATE PROCEDURE [Name]
AS
SET XACT_ABORT, NOCOUNT ON

DECLARE @starttrancount int

BEGIN TRY
    SELECT @starttrancount = @@TRANCOUNT

    IF @starttrancount = 0
        BEGIN TRANSACTION

       [...Perform work, call nested procedures...]

    IF @starttrancount = 0 
        COMMIT TRANSACTION
END TRY
BEGIN CATCH
    IF XACT_STATE() <> 0 AND @starttrancount = 0 
        ROLLBACK TRANSACTION
    RAISERROR [rethrow caught error using @ErrorNumber, @ErrorMessage, etc]
END CATCH
GO
7
gbn

J'utilise Essayer/Catch, mais je rassemble aussi autant d'informations que possible et écrivez-le à un errorLog après la restauration. Dans cet exemple, "LOGEFENT" est une procédure stockée qui écrit à une table EventLog, contenant les détails de ce qui s'est passé. Geterrrrrrrorinfo () est un appel de fonction qui renvoie le message d'erreur exact.

Lorsqu'une erreur se produit, les informations sont recueillies, la procédure dépasse la section de traitement des erreurs et émet une annulation. Les informations sont écrites sur le journal, puis la procédure sort.

Considérant les appels de procédure/fonctions supplémentaires impliqués, il semble un peu sur le dessus. Cependant, cette méthode est extrêmement utile lorsque vous essayez de déboguer le problème.

[.____] EXEC LOGEFENT @Process, @Database, "Tenter d'insérer Blah Blah bla" [.____] commencez à essayer 
 
 Sélectionnez @rowcount = @@ RowCount [.____] TRISY ESSAYER [.____] - ERREURMANDLING 
 Sélectionnez @Error = Error_Number ( ), 
 @rowcount = -1, [.____] @Tableaction = 'insert', [.____] @tabename = @Database + '.mytable', [.____] @AdditionalInfo = ' (Tentative d'insérer Blah Blah Blah) '+ dbo.geterrrrrinfo () 
 Goto TableAccessError 
 Capture final 
. ]. 
. 
 
 TableAccessError: [. ____ .____]] 'Erreur - une erreur s'est produite lorsqu'elle est survenue tandis que "+ 
 Cas (@Tableaction) [.____] [.] Lorsque" mise à jour ", alors" mise à jour "[. ____] alors" Supprimer "[supprimer' [ .____] sinon @Tableaction + 'ing '[.____] fin + 
' Records '+ 
 cas (@Tableaction) 
 Quand "Sélectionnez" alors "de" [. ____] 'In' 
 Quand "insérer" alors "dans" [.____] [. ____] "d'autre" de '
 fin + [.____] "The' + @tablename + 'Tableau.' 
 Sélectionnez @Output = @Output + '@@[email protected] erreur:' + Convertir (varchar (8), @ Erreur) [ 8), @ RowCount) [.____] [.____] Sélectionnez @Output = @Output + ISNULL (@AdditionAlinfo, '') [ ] RaisError (@ Sortie, 16,1) avec journal [.____] Sélectionnez @returnCode = -1 [.____] Goto the_exit [.____] [.____]
3
datagod