Je développe T-SQL depuis plusieurs années et j'approfondis sans cesse, continuant à apprendre tout ce que je peux sur tous les aspects de la langue. J'ai récemment commencé à travailler dans une nouvelle société et j'ai reçu ce que je pense est une suggestion étrange concernant les transactions. Ne les utilise jamais. Utilisez plutôt une solution de contournement qui simule une transaction. Cela vient de notre DBA qui travaille dans une base de données avec beaucoup de transactions et par la suite, beaucoup de blocage. La base de données dans laquelle je travaille principalement ne souffre pas de ce problème et je constate que des transactions ont déjà été utilisées.
Je comprends que le blocage des transactions est normal car il est de leur nature de le faire et si vous pouvez vous en tirer sans en utiliser une, faites-le. Mais il arrive souvent que chaque instruction DOIT être exécutée avec succès. Si on échoue, ils doivent tous ne pas s'engager.
J'ai toujours gardé le champ de mes transactions aussi étroit que possible, toujours utilisé avec SET XACT_ABORT ON et toujours dans un TRY / CATCH.
Exemple:
CREATE SCHEMA someschema;
GO
CREATE TABLE someschema.tableA
(id INT NOT NULL IDENTITY(1, 1) PRIMARY KEY,
ColA VARCHAR(10) NOT NULL
);
GO
CREATE TABLE someschema.tableB
(id INT NOT NULL IDENTITY(1, 1) PRIMARY KEY,
ColB VARCHAR(10) NOT NULL
);
GO
CREATE PROCEDURE someschema.ProcedureName @ColA VARCHAR(10),
@ColB VARCHAR(10)
AS
SET NOCOUNT, XACT_ABORT ON;
BEGIN
BEGIN TRY
BEGIN TRANSACTION;
INSERT INTO someschema.tableA(ColA)
VALUES(@ColA);
INSERT INTO someschema.tableB(ColB)
VALUES(@ColB);
--Implement error
SELECT 1/0
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
IF @@trancount > 0
BEGIN
ROLLBACK TRANSACTION;
END;
THROW;
RETURN;
END CATCH;
END;
GO
Voici ce qu'ils ont suggéré que je fasse.
GO
CREATE PROCEDURE someschema.ProcedureNameNoTransaction @ColA VARCHAR(10),
@ColB VARCHAR(10)
AS
SET NOCOUNT ON;
BEGIN
BEGIN TRY
DECLARE @tableAid INT;
DECLARE @tableBid INT;
INSERT INTO someschema.tableA(ColA)
VALUES(@ColA);
SET @tableAid = SCOPE_IDENTITY();
INSERT INTO someschema.tableB(ColB)
VALUES(@ColB);
SET @tableBid = SCOPE_IDENTITY();
--Implement error
SELECT 1/0
END TRY
BEGIN CATCH
DELETE FROM someschema.tableA
WHERE id = @tableAid;
DELETE FROM someschema.tableB
WHERE id = @tableBid;
THROW;
RETURN;
END CATCH;
END;
GO
Ma question à la communauté est la suivante. Est-ce que cela a du sens comme solution de contournement viable pour les transactions?
D'après ce que je sais des transactions et de la solution proposée, mon avis est que non, ce n'est pas une solution viable et présente de nombreux points d'échec.
Dans la solution de contournement suggérée, quatre transactions implicites se produisent. Les deux insère dans l'essai, puis deux autres transactions pour les suppressions dans la capture. Il «défait» les inserts mais sans rien annuler, donc rien n’est réellement annulé.
Ceci est un exemple très basique pour illustrer le concept proposé. Certaines des procédures stockées dans lesquelles j'ai effectué cette tâche sont extrêmement longues et difficiles à gérer, car il est très compliqué de "restaurer" plusieurs ensembles de résultats au lieu de deux valeurs de paramètre dans cet exemple. Puisque le "recul" est fait manuellement maintenant, l'occasion de rater quelque chose parce que c'est réel.
Je pense qu'un autre problème existe concerne les délais d'expiration ou les connexions rompues. Est-ce que cela est toujours annulé? C’est ainsi que je comprends pourquoi SET XACT_ABORT ON doit être utilisé pour que, dans ces cas, la transaction soit annulée.
Merci d'avance pour vos commentaires!