Antworten:
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:
Mit @ Rows = 100:
Mit @ Rows = 1000:
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".
begin tran
nur Zähler von Transaktionen erhöht. Wenn ich Sie verstanden habe, erledigt rdbms alle Aufgaben (verbindet Zeilen, generiert Ausführungspläne ...) bei COMMIT?
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
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 rollback
sein sollte , selten , in der Regel nur dann , wenn etwas schief gelaufen, und natürlich hat commit
wahrscheinlich viel häufiger sein - so es Sinn macht für optimizecommit
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).
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.
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).