Ist ROLLBACK eine schnelle Operation?

Antworten:

14

Für SQL Server könnte man argumentieren, dass ein Festschreibevorgang nichts anderes ist als das Schreiben von LOP_COMMIT_XACT in die Protokolldatei und das Aufheben von Sperren. Dies ist natürlich schneller als das ROLLBACK jeder Aktion, die Ihre Transaktion seit BEGIN TRAN ausgeführt hat.

Wenn Sie jede Aktion einer Transaktion in Betracht ziehen, nicht nur das Festschreiben, würde ich dennoch argumentieren, dass Ihre Aussage nicht wahr ist. Ohne externe Faktoren, z. B. Geschwindigkeit des Protokolldatenträgers im Vergleich zur Geschwindigkeit des Datendatenträgers, ist es wahrscheinlich, dass das Zurücksetzen von Arbeiten, die von einer Transaktion ausgeführt werden, schneller ist als das Ausführen der Arbeit an erster Stelle.

Ein Rollback liest eine sequentielle Änderungsdatei und wendet sie auf speicherinterne Datenseiten an. Die ursprüngliche "Arbeit" musste einen Ausführungsplan erstellen, Seiten erfassen, Zeilen verbinden usw.

Edit: Das kommt drauf an ...

@ JackDouglas verwies auf diesen Artikel, in dem eine der Situationen beschrieben wird, in denen das Zurücksetzen erheblich länger dauern kann als der ursprüngliche Vorgang. Das Beispiel ist eine 14-stündige Transaktion, bei der zwangsläufig Parallelität verwendet wird und die mehr als 48 Stunden für das Rollback benötigt, da das Rollback zumeist Single-Threaded-Transaktionen umfasst. Sie würden höchstwahrscheinlich auch den Pufferpool wiederholt umstellen, sodass Sie Änderungen an speicherinternen Seiten nicht mehr rückgängig machen.

Also eine überarbeitete Version meiner früheren Antwort. Wie viel langsamer ist das Rollback? Alles in allem ist dies bei einer typischen OLTP-Transaktion nicht der Fall. Außerhalb der typischen Grenzen kann es länger dauern, "rückgängig zu machen" als "zu machen", aber (ist dies ein möglicher Zungenbrecher?) Warum wird davon abhängen, wie das "machen" gemacht wurde.

Edit2: In Anlehnung an die Diskussion in den Kommentaren ist hier ein sehr ausgeklügeltes Beispiel, um zu demonstrieren, dass die geleistete Arbeit der Hauptfaktor bei der Bestimmung der relativen Kosten von Festschreibung im Vergleich zu Rollback als Operationen ist.

Erstellen Sie zwei Tabellen und packen Sie sie ineffizient (verschwendeter Speicherplatz pro Seite):

SET STATISTICS IO OFF;
SET STATISTICS TIME OFF;
SET NOCOUNT ON;
GO

CREATE TABLE dbo.Foo
(
    col1 INT IDENTITY(1,1) PRIMARY KEY CLUSTERED
    , col2 CHAR(4000) NOT NULL DEFAULT REPLICATE('A', 4000)
)

CREATE TABLE dbo.Bar
(
    col1 INT IDENTITY(1,1) PRIMARY KEY CLUSTERED
    , col2 CHAR(4000) NOT NULL DEFAULT REPLICATE('A', 4000)
)
GO

INSERT dbo.Foo DEFAULT VALUES
GO 100000

INSERT dbo.Bar DEFAULT VALUES
GO 100000

Führen Sie eine "fehlerhafte" Aktualisierungsabfrage aus, in der die für die Ausführung der Arbeit benötigte Zeit und die für die Ausgabe des Commits benötigte Zeit gemessen werden.

DECLARE 
    @StartTime DATETIME2
    , @Rows INT

SET @Rows = 1

CHECKPOINT
DBCC DROPCLEANBUFFERS

BEGIN TRANSACTION

SET @StartTime = SYSDATETIME()

UPDATE
    dbo.bar
SET
    col2 = REPLICATE('B', 4000)
FROM
    dbo.bar b
INNER JOIN
    (
    SELECT TOP(@Rows)
        col1
    FROM
        dbo.foo
    ORDER BY
        NEWID()
    ) f
ON  f.col1 = b.col1
OPTION (MAXDOP 1)

SELECT 'Find and update row', DATEDIFF(ms, @StartTime, SYSDATETIME())

SET @StartTime = SYSDATETIME()

COMMIT TRANSACTION

SELECT 'Commit', DATEDIFF(ms, @StartTime, SYSDATETIME())
GO

Wiederholen Sie den Vorgang, setzen Sie jedoch das Rollback ab und messen Sie es.

    DECLARE 
    @StartTime DATETIME2
    , @Rows INT

SET @Rows = 1

CHECKPOINT
DBCC DROPCLEANBUFFERS

BEGIN TRANSACTION

SET @StartTime = SYSDATETIME()

UPDATE
    dbo.bar
SET
    col2 = REPLICATE('B', 4000)
FROM
    dbo.bar b
INNER JOIN
    (
    SELECT TOP(@Rows)
        col1
    FROM
        dbo.foo
    ORDER BY
        NEWID()
    ) f
ON  f.col1 = b.col1
OPTION (MAXDOP 1)

SELECT 'Find and update row', DATEDIFF(ms, @StartTime, SYSDATETIME())

SET @StartTime = SYSDATETIME()

ROLLBACK TRANSACTION

SELECT 'Rollback', DATEDIFF(ms, @StartTime, SYSDATETIME())
GO

Mit @ Rows = 1 bekomme ich eine einigermaßen konsistente:

  • 5500ms für die Suche / Aktualisierung
  • 3ms festschreiben
  • 1ms Rollback

Mit @ Rows = 100:

  • 8500ms suchen / aktualisieren
  • 15ms festschreiben
  • 15ms Rollback

Mit @ Rows = 1000:

  • 15000ms suchen / aktualisieren
  • 10ms festschreiben
  • 500ms Rollback

Zurück zur ursprünglichen Frage. Wenn Sie die für die Ausführung der Arbeit benötigte Zeit plus das Festschreiben messen, gewinnt das Rollback zweifellos an Bedeutung, da der größte Teil dieser Arbeit darauf verwendet wird, die zu aktualisierende Zeile zu finden und nicht die Daten tatsächlich zu ändern. Wenn Sie die Festschreibungsoperation isoliert betrachten, sollte klar sein, dass die Festschreibungsoperation als solche nur sehr wenig "funktioniert". Commit ist "Ich bin fertig".

Mark Storey-Smith
quelle
2
"Weniger Arbeit" ist nicht unbedingt "schneller"
Jack Douglas
Ich wusste, dass begin trannur Zähler von Transaktionen erhöht. Wenn ich Sie verstanden habe, erledigt rdbms alle Aufgaben (verbindet Zeilen, generiert Ausführungspläne ...) bei COMMIT?
Garik
3
Nein, alle Arbeiten werden vor dem Festschreiben ausgeführt. Die Festschreibungsoperation selbst macht vergleichsweise wenig.
Mark Storey-Smith
@Mark Ich habe einige grobe und vorbereitete Tests durchgeführt, bei denen 2-Meter-Zeilen eingefügt wurden und die entweder festgeschrieben oder zurückgesetzt wurden. Die Gesamtzeit einschließlich Rollback lag zwischen 10 und 30 Sekunden, während die Gesamtzeit einschließlich Commit zwischen 6 und 14 Sekunden lag. YMMV natürlich, aber dies deutet darauf hin, dass das Rollback des Baseballstadions zumindest in meiner Umgebung fast so lange oder länger dauert als die ursprüngliche Transaktion.
Jack Douglas
2
Wenn Sie die Zeit für den Abschluss des Festschreibungsvorgangs messen würden, würde ich davon ausgehen, dass sie minimal ist, es sei denn, es wird gleichzeitig ein Prüfpunkt ausgegeben (der separat und unabhängig ist). Das ist meine Art von Punkt, das Festschreiben macht sehr wenig, während das Zurücksetzen alles macht, was vor dem Festschreiben geschah, plus ein bisschen mehr. Die Abweichungen in Ihren Tests lassen andere Faktoren vermuten, aber ich werde auf jeden Fall versuchen, später einige Skripte zusammenzustellen.
Mark Storey-Smith
13

Bei Oracle kann das Rollback um ein Vielfaches länger dauern als das Vornehmen der rückgängig gemachten Änderungen. Dies spielt oft keine Rolle, weil

  1. Während des Rollbacks der Transaktion werden keine Sperren gehalten
  2. Es wird von einem Hintergrundprozess mit niedriger Priorität verarbeitet

Für SQL Server bin ich mir nicht sicher, ob die Situation die gleiche ist, aber jemand anderes wird sagen, ob es nicht ...

Wie bei den „Warum“, würde ich sagen , das rollbacksein sollte , selten , in der Regel nur dann , wenn etwas schief gelaufen, und natürlich hat commitwahrscheinlich viel häufiger sein - so es Sinn macht für optimizecommit

Jack Douglas
quelle
9

Rollback ist nicht nur "oh, egal" - in vielen Fällen muss es wirklich rückgängig machen, was es bereits getan hat. Es gibt keine Regel, dass der Rollback-Vorgang immer langsamer oder immer schneller als der ursprüngliche Vorgang ist, auch wenn die ursprüngliche Transaktion parallel ausgeführt wurde, erfolgt der Rollback mit einem Thread. Wenn Sie warten, ist es am sichersten, einfach weiter zu warten.

Dies ändert sich natürlich alles mit SQL Server 2019 und der beschleunigten Datenbankwiederherstellung (die bei einer ebenfalls variablen Strafe ein sofortiges Rollback unabhängig von der Datengröße ermöglicht).

Aaron Bertrand
quelle
2
Und wir hatten alle das Gefühl, dass es eine Ewigkeit dauert, ein Rollback durchzuführen, lasst es uns neu starten, oder?
Mark Storey-Smith
Ich habe viele Kunden gesehen, die das gemacht haben. Einige bleiben relativ unversehrt, andere haben weniger Glück.
Aaron Bertrand
1
@ MarkStorey-Smith - Wenn Sie mitten im Rollback einen Neustart durchführen, muss SQL Server den Rollback dann trotzdem beim Start fortsetzen?
Nick Chammas
2
@Nick das hängt davon ab - wenn das Rollback beispielsweise vor dem Neustart blockiert wurde, verhält es sich nach einem Neustart des Dienstes möglicherweise viel schneller, da dieser andere Prozess gerade beendet wurde. In diesem Szenario gibt es VIELES "Was wäre wenn". Jedes Mal, wenn Sie einen Server neu starten oder einen Dienst neu starten, um ein Problem zu "beheben", treten möglicherweise erheblich schwerwiegendere Probleme auf.
Aaron Bertrand
2
@ Nick, ja genau das passiert. Mein Kommentar sollte "Zunge in der Wange" sein, so dass Sie das unweigerlich dem auslösenden fröhlichen Volk erklären müssen, das einen Neustart durchführen möchte, wenn sich etwas nicht wie erwartet verhält.
Mark Storey-Smith
8

Nicht für alle Transaktionen ist die Leistung ihrer Festschreibungsaktivität wesentlich besser als die ihres Rollbacks. Ein solcher Fall ist der Löschvorgang in SQL. Wenn eine Transaktion Zeilen löscht, werden diese Zeilen als Geisterdatensätze markiert. Sobald ein Commit ausgeführt wurde und eine Bereinigungsaufgabe für Geisterdatensätze gestartet wurde, werden nur diese Datensätze "gelöscht".

Wenn stattdessen ein Rollback ausgegeben wurde, werden nur die Geisterzeichen aus diesen Datensätzen entfernt und nicht die intensiven Einfügeanweisungen.

StanleyJohns
quelle
Ein gutes Beispiel dafür, wie bestimmte Vorgänge für das Rollback optimiert werden.
Mark Storey-Smith
5

Nicht alle sind es. Das Zurücksetzen von PostgreSQL dauert nicht länger als das Festschreiben, da die beiden Vorgänge hinsichtlich der Festplatten-E / A praktisch identisch sind. Ich denke nicht, dass dies eine Frage der Commit-Optimierung ist, sondern vielmehr, wofür andere Abfragen optimiert werden.

Die grundlegende Frage ist, wie Sie das Layout auf der Festplatte ansprechen und wie sich dies auf das Festschreiben gegenüber dem Rollback auswirkt. Die Hauptdatenbanken, die langsamer als das Festschreiben zurückgesetzt werden, neigen dazu, Daten, insbesondere aus gruppierten Tabellen, aus den Hauptdatenstrukturen zu verschieben und beim Aktualisieren der Daten in ein Rollback-Segment zu verschieben. Dies bedeutet, dass Sie zum Festschreiben nur das Rollback-Segment löschen, zum Rollback jedoch alle Daten zurückkopieren müssen.

Bei PostgreSQL sind alle Tabellen Heap-Tabellen und Indizes getrennt. Dies bedeutet, dass beim Zurücksetzen oder Festschreiben keine Daten neu angeordnet werden müssen. Dadurch werden Commit und Rollback schnell ausgeführt.

Es macht jedoch einige andere Dinge etwas langsamer. Eine Primärschlüsselsuche muss zum Beispiel eine Indexdatei durchlaufen und dann die Heap-Tabelle erreichen (vorausgesetzt, es gibt keine zutreffenden überdeckenden Indizes). Dies ist keine große Sache, fügt jedoch eine zusätzliche Seitensuche oder sogar ein paar zufällige Seitensuchen hinzu (wenn in dieser Zeile viele Aktualisierungen stattgefunden haben), um nach weiteren Informationen und Sichtbarkeit zu suchen.

Die Geschwindigkeit ist hier jedoch keine Frage der Optimierung in PostgreSQL für Schreibvorgänge im Vergleich zu Lesevorgängen. Es ist nicht gewillt, einige Lesevorgänge vor anderen zu privilegieren. Folglich schneidet PostgreSQL im Durchschnitt ungefähr so ​​gut ab wie die anderen DBs. Es sind nur bestimmte Vorgänge, die schneller oder langsamer sein können.

Ich denke, die eigentliche Antwort ist, dass DBs für bestimmte Workloads auf der Leseseite optimiert sind und dies zu Herausforderungen auf der Schreibseite führt. In der Regel werden Commits bei Fragen in der Regel, wenn auch nicht immer, Rollbacks vorgezogen. Dies hängt jedoch von den Auswirkungen einer der beiden Aktionen ab (Aktualisierungen unterscheiden sich von Löschvorgängen).

Chris Travers
quelle
Gute Antwort, aber ein kleines Problem: "Für PostgreSQL sind alle Tabellen Heap-Tabellen und Indizes getrennt. Dies bedeutet, dass beim Zurücksetzen oder Festschreiben keine Daten neu angeordnet werden müssen." Dies ist nicht der Grund, warum keine Daten neu angeordnet werden müssen Es liegt vielmehr daran, dass "die Hauptdatenbanken, die langsamer zurücklaufen als das Festschreiben, dazu neigen, Daten zu verschieben", und pg nicht, wie Sie erwähnt haben. Oracle verwendet standardmäßig auch Heap-Speicher: Der Hauptunterschied besteht darin, dass Oracle die Option "Rückgängig" verwendet und beim Festschreiben / Rollback den gesamten Speicherplatz zurückerhält, anstatt die "Vakuum" -Route einzuschlagen.
Jack Douglas