Ceci est notre modèle (erreur de journalisation supprimée)
Ceci est conçu pour gérer
- Article de Paul Randal "Il n'y a pas de transaction imbriquée dans SQL Server"
- Erreur 266
- Déclencher des restaurations
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