Verwenden Sie keine Transaktion für gespeicherte Prozeduren
18
Ich habe eine gespeicherte Prozedur, die einige Befehle ausführt. Ich möchte nicht, dass diese Befehle in die Transaktion der gespeicherten Prozedur eingeschlossen werden. Wenn der 4. Befehl fehlschlägt, soll der 1., 2. und 3. Befehl erhalten bleiben und nicht zurückgesetzt werden.
Ist es möglich, die gespeicherte Prozedur so zu schreiben, dass nicht alles als eine große Transaktion ausgeführt wird?
Alle Transaktionen werden nicht in einer einzigen Transaktion ausgeführt. Schauen Sie sich dieses Beispiel an:
use TestDB;
go
ifexists(select1from sys.tables where object_id = object_id('dbo.TestTranTable1'))droptable dbo.TestTranTable1;createtable dbo.TestTranTable1
(
id int identity(1,1)notnull,
some_int int notnulldefault1);
go
insertinto dbo.TestTranTable1
defaultvalues;
go 4select*from dbo.TestTranTable1;ifexists(select1from sys.sql_modules where object_id = object_id('dbo.ChangeValues'))begindropproc dbo.ChangeValues;end
go
createproc dbo.ChangeValues
asupdate dbo.TestTranTable1
set some_int =11where id =1;update dbo.TestTranTable1
set some_int =12where id =2;update dbo.TestTranTable1
set some_int =13where id =3;-- this will error out (arithmetic overflow)update dbo.TestTranTable1
set some_int =2147483648where id =4;
go
exec dbo.ChangeValues;select*from dbo.TestTranTable1;
Hier ist die Ausgabe:
Wenn Sie eine Extended Events-Sitzung zur Überwachung des sql_transactionEreignisses erstellen , sehen Sie hier die Ausgabe der Ausführung dbo.ChangeValues:
Wie Sie in diesem Screenshot oben sehen können, gibt es für jede der vier Anweisungen separate Transaktionen. Die ersten 3 Commits und die letzten 3 Commits werden aufgrund des Fehlers zurückgesetzt.
Ich denke, dass es hier einige Verwirrung über einen Stapel gegen eine Transaktion geben kann .
Eine Transaktion ist eine Anweisung oder eine Gruppe von Anweisungen, die als Einheit erfolgreich sind oder fehlschlagen. Alle DDL-Anweisungen befinden sich in Transaktionen selbst (dh wenn Sie 100 Zeilen aktualisieren, Zeile 98 jedoch einen Fehler ausgibt, wird keine der Zeilen aktualisiert). Sie können auch eine Reihe von Anweisungen in eine Transaktion einschließen, indem Sie BEGIN TRANSACTIONund dann entweder COMMIToder verwenden ROLLBACK.
Ein Batch ist eine Reihe von Anweisungen, die zusammen ausgeführt werden. Eine gespeicherte Prozedur ist ein Beispiel für einen Stapel. Wenn in einer gespeicherten Prozedur eine Anweisung fehlschlägt und eine Fehlerbehandlung (normalerweise TRY/CATCHBlöcke) vorliegt, werden die nachfolgenden Anweisungen nicht ausgeführt.
Ich vermute, dass Ihr Problem darin besteht, dass der Stapel abgebrochen wird, wenn ein Fehler auftritt, weil entweder der gespeicherte Prozess selbst oder ein äußerer Bereich (wie die Anwendung oder der gespeicherte Prozess, der diese Prozedur aufruft) eine Fehlerüberwachung enthält. In diesem Fall ist die Lösung schwieriger, da Sie die Behandlung von Fehlern in dem Bereich anpassen müssen, in dem sie abgefangen werden.
Ich habe keinen Artikel gefunden, in dem steht: "Eine Speicherprozedur ist ein Beispiel für einen Stapel". Ich glaube, dass gespeicherte Prozedur Batch sehr ähnlich ist, aber es ist kein Batch. Der Hauptunterschied besteht darin, dass SP im Gegensatz zu Batches garantiert im Voraus kompiliert und mehrmals ausgeführt werden kann. Die Ähnlichkeiten sind: - Beide führen jeden Befehl gleichzeitig aus. - Wenn ein Befehl fehlgeschlagen ist, werden alle vorherigen Befehle festgeschrieben (es sei denn, es wurde in einer Transaktion ausgeführt). - Wenn ein Befehl fehlgeschlagen ist, werden nicht alle nächsten Befehle ausgeführt.
Ashi
6
Alles in SQL Server ist in einer Transaktion enthalten.
Wenn Sie explizit angeben begin transactionund end transactiondann heißt es Explicit Transaction . Wenn Sie dies nicht tun, handelt es sich um eine implizite Transaktion .
Um zu wechseln, in welchem Modus Sie sich befinden, verwenden Sie
set implicit_transactions on
oder
set implicit_transactions offselect@@OPTIONS &2
Wenn oben 2 zurückgegeben wird, befinden Sie sich im impliziten Transaktionsmodus. Wenn es 0 zurückgibt, werden Sie automatisch festgeschrieben.
Eine Transaktion ist ALL oder nichts, um die Datenbank in einem konsistenten Zustand zu halten. Beachten Sie die ACID-Eigenschaften.
So funktionieren gespeicherte Prozeduren standardmäßig. Die gespeicherte Prozedur wird nicht automatisch in eine Transaktion eingeschlossen.
Wenn die gespeicherte Prozedur angehalten werden soll, wenn der erste Fehler auftritt, müssen Sie einige TRY / CATCH-Anmeldedaten eingeben, um sie beispielsweise bei einem Problem mit Befehl 2 zurückzugeben.
Ich möchte, dass einzelne Transaktionen das Standardverhalten für gespeicherte Prozeduren sind, da alle Anweisungen in implizite Transaktionen eingeschlossen sind. Niemand sollte sich jedoch auf implizite Transaktionen verlassen, um das Schicksal seines Codes zu kontrollieren. Es ist weitaus besser, die Art und Weise, wie Transaktionen im Produktionscode verarbeitet werden, explizit zu steuern.
Trennen Sie jedes der Teile mit einem BEGIN TRAN und prüfen Sie, ob die Transaktion erfolgreich war. Wenn es ein Commit war, führen Sie andernfalls ein Rollback durch, da sie alle auf derselben Ebene ausgeführt werden. Sie können jeden Abschnitt separat festschreiben, ohne alle zurücksetzen zu müssen, wenn einer fehlschlägt.
Werden dadurch Untertransaktionen in meiner gespeicherten Prozedur erstellt? Im Idealfall möchte ich das nach Möglichkeit vermeiden
Matthew Steeples
1
Wenn der SP innerhalb einer Transaktion aufgerufen wird, sind die oben gespeicherten Transaktionen die Antwort. Wenn der sp nicht mit aufgerufen wird, ist @mrdenny korrekt. SQL Server unterstützt keine verschachtelten Transaktionen.
Um klar zu sein (und für die Faulen, die nicht auf die Links klicken möchten), starten Sie eigentlich keine weitere Transaktion. Aka der Titel auf Pauls Post: "Mythos: Verschachtelte Transaktionen sind real." Sie sind keine wirklichen Transaktionen. COMMIT in einer verschachtelten Transaktion bewirkt nichts anderes als das Dekrementieren von @@ TRANCOUNT. Es ist wahr, dass Sie keine Fehlermeldung erhalten, wenn Sie BEGIN TRAN / COMMIT verschachteln. Dies unterscheidet sich jedoch von echten verschachtelten Transaktionen.
Alles in SQL Server ist in einer Transaktion enthalten.
Wenn Sie explizit angeben
begin transaction
undend transaction
dann heißt es Explicit Transaction . Wenn Sie dies nicht tun, handelt es sich um eine implizite Transaktion .Um zu wechseln, in welchem Modus Sie sich befinden, verwenden Sie
oder
Wenn oben 2 zurückgegeben wird, befinden Sie sich im impliziten Transaktionsmodus. Wenn es 0 zurückgibt, werden Sie automatisch festgeschrieben.
Eine Transaktion ist ALL oder nichts, um die Datenbank in einem konsistenten Zustand zu halten. Beachten Sie die ACID-Eigenschaften.
- SP jetzt erstellen - Beachten Sie, dass die ersten 3 erfolgreich sind und die 4. fehlschlägt, wenn die Zeichenfolge abgeschnitten wird ...
Siehe auch: Ist es eine schlechte Praxis, immer eine Transaktion zu erstellen?
quelle
So funktionieren gespeicherte Prozeduren standardmäßig. Die gespeicherte Prozedur wird nicht automatisch in eine Transaktion eingeschlossen.
Wenn die gespeicherte Prozedur angehalten werden soll, wenn der erste Fehler auftritt, müssen Sie einige TRY / CATCH-Anmeldedaten eingeben, um sie beispielsweise bei einem Problem mit Befehl 2 zurückzugeben.
quelle
Sie benötigen für jeden Befehl einzelne Transaktionen. Sie können dies auch mit gespeicherten Transaktionen durchführen:
Siehe
SAVE TRANSACTION (Transact-SQL)
in der Produktdokumentation.Ich möchte, dass einzelne Transaktionen das Standardverhalten für gespeicherte Prozeduren sind, da alle Anweisungen in implizite Transaktionen eingeschlossen sind. Niemand sollte sich jedoch auf implizite Transaktionen verlassen, um das Schicksal seines Codes zu kontrollieren. Es ist weitaus besser, die Art und Weise, wie Transaktionen im Produktionscode verarbeitet werden, explizit zu steuern.
quelle
Trennen Sie jedes der Teile mit einem BEGIN TRAN und prüfen Sie, ob die Transaktion erfolgreich war. Wenn es ein Commit war, führen Sie andernfalls ein Rollback durch, da sie alle auf derselben Ebene ausgeführt werden. Sie können jeden Abschnitt separat festschreiben, ohne alle zurücksetzen zu müssen, wenn einer fehlschlägt.
Weitere Informationen finden Sie unter: http://msdn.microsoft.com/en-us/library/ms188929.aspx
quelle