Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Verwenden von Transaktion ROLLBACK in SQL Server

Einführung

Vor kurzem kam ein Kollege von mir verzweifelt zu mir und gab zu, dass er eine Update-Anweisung ohne WHERE-Klausel für eine Schlüsselanwendungstabelle ausgegeben hatte. Die Auswirkungen auf das Frontend wären katastrophal, also kam er direkt zu mir, weil er dringend Hilfe brauchte, um die Situation um jeden Preis umzukehren, bevor die E-Mails und die Eskalation eintrafen.

Als wir uns die Situation angesehen haben, haben wir festgestellt, dass die Änderungen nicht in der sekundären Datenbank übernommen wurden. In den meisten Fällen beträgt die Verzögerung zwischen unserer primären und sekundären Datenbank zwanzig Minuten (wir haben eine kleine Staffelung, um Leistungsprobleme zu vermeiden). Da mein Kollege sofort nach Erkennen des Fehlers um Hilfe bat, konnten wir die Daten aus der sekundären Datenbank wiederherstellen. Ich habe den Wert einer solchen Verzögerung in diesem Artikel beschrieben .

Szenarioüberprüfung

Das oben beschriebene Szenario ist nicht ungewöhnlich. Einer der Gründe, warum dies normalen Benutzern von SQL Server passiert, ist, dass SQL Server sogenannte implizite Transaktionen verwendet. Implizite Transaktionen sind standardmäßig deaktiviert, was bedeutet, dass SQL Server nicht erwartet, dass Sie am Ende jeder Anweisung eine COMMIT TRANSACTION-Anweisung ausgeben. Tatsächlich wird jede Anweisung automatisch festgeschrieben. Dies ist praktisch und hilft, Situationen zu vermeiden, in denen Sitzungen, die noch festgeschrieben werden müssen, am Ende Ressourcen sperren und die Leistung beeinträchtigen. Brent Ozar enthält weitere Details zu den Leistungsauswirkungen von IMPLICIT TRANSACTIONS =ON.

Ein kleiner Nachteil dieser Konfiguration (IMPLICIT TRANSACTIONS =OFF) ist jedoch, dass Benutzer keine Gelegenheit haben, eine Anweisung zu überdenken und ein ROLLBACK auszuführen, was in Oracle sehr üblich ist. Abb. 1 zeigt die in SQL Server Management Studio verfügbaren ANSI-Abfrageoptionen.

Abb. 1 ANSI-Standardwerte in SQL Server Management Studio

Implizite Transaktionen verwenden

Im Wesentlichen besteht das Problem, mit dem wir in dieser Standardkonfiguration oder unserem wünschenswertesten Client-Tool konfrontiert sind, darin, dass wir kein ROLLBACK durchführen können, sobald wir eine SQL-Anweisung ausgeführt haben. Wir können dies umgehen, indem wir IMPLICIT TRANSACTIONS in unserer Sitzung aktivieren. Dies gibt uns die Möglichkeit, Transaktionen bei Bedarf rückgängig zu machen. Abb. 2 und Abb. 4 zeigen uns, dass wir diese Einstellung nur für eine Sitzung aktivieren können, obwohl dies nicht das Risiko beseitigt, dass die Benutzersitzung andere blockiert, wenn kein ROLLBACK oder COMMIT ausgegeben wird.

Abb. 2 IMPLIZITE TRANSAKTIONEN EIN in einer Sitzung

-- Listing 1: UPDATE Table TAB2 with IMPLICIT_TRANSACTIONS ON
SET IMPLICIT_TRANSACTIONS ON

DECLARE @IMPLICIT_TRANSACTIONS VARCHAR(3) = 'OFF';  
IF ( (2 & @@OPTIONS) = 2 ) SET @IMPLICIT_TRANSACTIONS = 'ON';  
SELECT @IMPLICIT_TRANSACTIONS AS IMPLICIT_TRANSACTIONS;

USE KTrain
GO
SELECT * FROM Tab2;
GO

UPDATE TAB2
SET countryCode='SA'
-- WHERE fname='Joyce';
GO
SELECT * FROM Tab2;
GO

Abb. 3 Alle Zeilen aktualisiert

Um die hier beschriebene Problemumgehung zu veranschaulichen, sehen wir uns den SQL-Code in Listing 1 an. Nehmen wir an, dass ein normaler SQL Server-Benutzer, ein Junior-Entwickler, eine Reihe von Skripten erhalten hat, die unter bestimmten Bedingungen ausgeführt werden . In dem Skript wurde die WHERE-Klausel auskommentiert, weil erwartet wird, dass sie jedes Mal, wenn sie dieses Skript ausführen, das Prädikat ändern sollten. Dies ist natürlich ein einfacher Anwendungsfall und das Risiko kann auf verschiedene Weise angegangen werden, aber wir möchten nur die Möglichkeit aufzeigen, ein ROLLBACK durchzuführen.

Denken Sie daran, dass wir IMPLICIT TRANSACTION bereits aktiviert haben. Wenn wir also diese Anweisung ausführen, erwartet SQL Server, dass wir die Transaktion entweder COMMIT oder ROLLBACK ausführen. Die Absicht des Entwicklers ist es, den countryCode von Joyce Afam zu aktualisieren nach „SA“, da sie nach Südafrika eingewandert ist. Abb. 3 zeigt uns, dass der Entwickler dabei versehentlich alle Zeilen mit dem Wert SA als countryCode aktualisiert hat . Sie bemerken dies und geben ein ROLLBACK aus.

Abb. 4 Ausgabe von ROLLBACK

Abb. 5 IMPLIZITE TRANSAKTIONEN EIN in einer anderen Sitzung

In der anderen Sitzung, in der wir IMPLIZITE TRANSAKTIONEN nicht aktiviert haben, stellen wir jedoch fest, dass der Entwickler seinen Fehler nicht beheben kann. Sie können in diesem Fall kein ROLLBACK erfolgreich ausgeben. Eine Wiederherstellung würde dann eine Datenwiederherstellung nach sich ziehen.

Abb. 6 ROLLBACK nicht möglich ohne IMPLICIT TRANSACTIONS ON

Explizite Transaktionen verwenden

Ein anderer Ansatz, um denselben Effekt zu erzielen, besteht darin, die DML in eine Transaktion einzuschließen, indem explizit BEGIN TRAN angegeben wird. Auch hier ist es sehr wichtig, die Transaktion abzuschließen – entweder mit COMMIT oder ROLLBACK. Im Rahmen dieser Diskussion geben wir ein ROLLBACK aus, da wir feststellen, dass ein Fehler im Code vorliegt.

-- Listing 2: UPDATE Table TAB2 with Explicit Transaction

BEGIN TRAN 
GO
USE KTrain
GO
SELECT * FROM Tab2;
GO

UPDATE TAB2
SET countryCode='GH'
-- WHERE fname='Joyce';
GO
SELECT * FROM Tab2;
GO

ROLLBACK;

SELECT * FROM Tab2;
GO

- Listing 3: Corrected UPDATE Statement

BEGIN TRAN 
GO
USE KTrain
GO
SELECT * FROM Tab2;
GO

UPDATE TAB2
SET countryCode='SA'
WHERE fname='Joyce';
GO
SELECT * FROM Tab2;
GO

Schlussfolgerung

In diesem Artikel haben wir kurz eine gute Problemumgehung angesprochen, um Möglichkeiten für ROLLBACK zu schaffen und so Benutzerfehler aufgrund falscher DML zu verringern. Wir haben auch ein Hauptrisiko dieses Ansatzes hervorgehoben, nämlich das versehentliche Blockieren. Ein DBA kann mit Untersuchungen zum möglichen Vorhandensein dieses Risikos beginnen, indem er sys.dm_tran_session_transactions, sys.dm_tran_locks abfragt , und ähnliche dynamische Verwaltungsobjekte.

Referenzen

  1. Behebung von Datenverlust durch Protokollversand mit verzögerter Wiederherstellung

  2. Implizite Transaktionen festlegen

  3. Implizite Transaktionen als schlechte Idee ansehen

  4. DMVs für Transaktionen