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

Procédures stockées imbriquées contenant le modèle TRY CATCH ROLLBACK ?

Ceci est notre modèle (erreur de journalisation supprimée)

Ceci est conçu pour gérer

Explications :

  • tous les TXN begin et commit/rollbacks doivent être jumelés de sorte que @@TRANCOUNT est le même à l'entrée et à la sortie

  • incompatibilités de @@TRANCOUNT provoquer l'erreur 266 car

    • BEGIN TRAN incrémente @@TRANCOUNT

    • COMMIT décrémente @@TRANCOUNT

    • ROLLBACK renvoie @@TRANCOUNT à zéro

  • Vous ne pouvez pas décrémenter @@TRANCOUNT pour le champ d'application actuel
    C'est ce que vous pensez être la "transaction interne"

  • SET XACT_ABORT ON supprime l'erreur 266 causée par @@TRANCOUNT non concordant
    Et traite également des problèmes comme celui-ci "SQL Server Transaction Timeout" sur dba.se

  • Cela permet des TXN côté client (comme LINQ) Une seule procédure stockée peut faire partie d'une transaction distribuée ou XA, ou simplement initiée dans le code client (par exemple .net TransactionScope)

Utilisation :

  • Chaque proc stocké doit être conforme au même modèle

Résumé

  • Donc, ne créez pas plus de TXN que nécessaire

Le code

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;
    THROW;
    --before SQL Server 2012 use 
    --RAISERROR [rethrow caught error using @ErrorNumber, @ErrorMessage, etc]
END CATCH
GO

Remarques :

  • La vérification de la restauration est en fait redondante à cause de SET XACT_ABORT ON . Cependant, cela me fait me sentir mieux, a l'air bizarre sans et permet des situations où vous ne le voulez pas

  • Remus Rusanu a un shell similaire qui utilise des points de sauvegarde. Je préfère un appel de base de données atomique et n'utilise pas de mises à jour partielles comme leur article