Ich habe T-SQL seit mehreren Jahren entwickelt und beschäftige mich ständig weiter mit allen Aspekten der Sprache. Ich habe vor kurzem angefangen, in einem neuen Unternehmen zu arbeiten, und habe einen meiner Meinung nach merkwürdigen Vorschlag für Transaktionen erhalten. Benutze sie niemals. Verwenden Sie stattdessen eine Problemumgehung, die eine Transaktion simuliert. Dies kommt von unserem DBA, der in einer Datenbank mit vielen Transaktionen und anschließend vielen Blockierungen arbeitet. Die Datenbank, in der ich hauptsächlich arbeite, ist von diesem Problem nicht betroffen, und ich sehe, dass in der Vergangenheit Transaktionen verwendet wurden.
Ich verstehe, dass das Blockieren von Transaktionen erwartet wird, da dies in der Natur der Sache liegt. Aber ich habe viele Gelegenheiten, in denen jede Anweisung erfolgreich ausgeführt werden muss. Wenn einer ausfällt, müssen alle das Commit nicht ausführen.
Ich habe den Umfang meiner Transaktionen immer so eng wie möglich gehalten, immer in Verbindung mit SET XACT_ABORT ON und immer innerhalb eines TRY / CATCH.
Beispiel:
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
Hier ist, was sie mir vorgeschlagen haben.
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
Meine Frage an die Community lautet wie folgt. Ist dies als praktikable Abhilfemaßnahme für Transaktionen sinnvoll?
Meine Meinung nach weiß ich über Transaktionen Bescheid und die Lösung schlägt vor, nein, dies ist keine praktikable Lösung und führt viele Fehlerquellen ein.
In der vorgeschlagenen Problemumgehung werden vier implizite Transaktionen angezeigt. Die zwei Einfügungen im Versuch und dann zwei weitere Transaktionen für die Löschungen im Fang. Die Einfügungen werden zwar rückgängig gemacht, jedoch ohne dass ein Rollback ausgeführt wird, sodass tatsächlich kein Rollback ausgeführt wird.
Dies ist ein sehr einfaches Beispiel, um das vorgeschlagene Konzept zu demonstrieren. Einige der tatsächlich gespeicherten Prozeduren, in denen ich dies getan habe, machen sie sehr lang und schwierig zu verwalten, da das Zurücksetzen mehrerer Ergebnismengen gegenüber zwei Parameterwerten in diesem Beispiel ziemlich kompliziert wird, wie Sie sich vorstellen können. Da "Zurückrollen" jetzt manuell gemacht wird, besteht die Möglichkeit, da echt etwas zu verpassen.
Ein weiteres Problem, das meines Erachtens besteht, sind Zeitüberschreitungen oder unterbrochene Verbindungen. Wird dies immer noch rückgängig gemacht? Nach meinem Verständnis sollte SET XACT_ABORT ON verwendet werden, damit in diesen Fällen die Transaktion zurückgesetzt wird.
Vielen Dank für Ihr Feedback im Voraus!