Wie unterscheiden sich diese beiden SQL Server-Rollbacks?

13

Wie unterscheiden sich diese beiden Rollbacks in SQL Server 2008 R2?

  1. Führen Sie ALTEReinige Minuten lang eine Anweisung aus und klicken Sie dann auf "Ausführung abbrechen". Das vollständige Zurücksetzen dauert einige Minuten.

  2. Führen Sie dieselbe ALTERAnweisung aus, stellen Sie jedoch sicher, dass die LDFDatei nicht groß genug ist, um erfolgreich abgeschlossen zu werden. Sobald das LDFLimit erreicht ist und kein "Autogrowth" mehr zulässig ist, wird die Ausführung der Abfrage mit der folgenden Fehlermeldung sofort gestoppt (oder ein Rollback wird durchgeführt):

The statement has been terminated.
Msg 9002, Level 17, State 4, Line 1
The transaction log for database 'SampleDB' is full. 
To find out why space in the log cannot be reused, see the 
log_reuse_wait_desc column in sys.databases

Wie unterscheiden sich diese beiden in den folgenden Punkten?

  1. Warum erfolgt das zweite Zurücksetzen sofort? Ich bin nicht ganz sicher, ob es ein Rollback genannt werden könnte. Ich vermute, das Transaktionsprotokoll wird im Verlauf der Ausführung geschrieben, und sobald festgestellt wird, dass nicht genügend Speicherplatz vorhanden ist, um die Aufgabe vollständig abzuschließen, wird es nur mit einer Endmeldung ohne Festschreibung angehalten.

  2. Was passiert, wenn der erste Rollback so viel Zeit in Anspruch nimmt (ist ein Rollback Single Thread)?
    2.1. Geht SQL Server zurück und macht die in der LDFDatei vorgenommenen Einträge rückgängig ?
    2.2. Die LDFDateigröße wird am Ende des Rollbacks kleiner (von DBCC SQLPERF(LOGSPACE))

  3. Eine weitere Frage: Während des zweiten Szenarios beginnt SQL Server LDFziemlich schnell , Dateien zu verbrauchen . In meinem Fall stieg die Auslastung in den ersten Minuten (<4 Minuten) von 18% auf 90%. Sobald es 99% erreicht hatte, blieb es dort für weitere 8 Minuten, während der Verbrauch zwischen 99,1% und 99,8% schwankte. Es steigt (99,8%) und sinkt (99,2%) und steigt (99,7%) und sinkt (99,5%) einige Male, bevor der Fehler ausgelöst wird. Was passiert hinter den Kulissen?

Alle MSDN-Links, die dies näher erläutern könnten, sind willkommen.

Auf Vorschlag von Ali Razeghi füge ich perfmon hinzu: Disk Bytes/sec

Szenario 1:

Szenario 1

Szenario 2:

Szenario 2

ToC
quelle
Nur ein kurzer Kommentar: Dateigröße! = In einer Datei verwendeter Speicherplatz.
Aaron Bertrand
@ Aaron Ja, das kenne ich. Ich habe DBCC SQLPERF (LOGSPACE) verwendet, um die Nutzung zu messen. Die LDF-Datei blieb während der gesamten Dauer gleich, da ich die Dateigröße auf 10 GB begrenzt habe. Die interne Verwendung variiert.
ToC
1
Ich vermute, dass das zweite Rollback sofort angezeigt wird , da der Fehler gemeldet wird, nachdem das Rollback abgeschlossen ist. Dies sind wahrscheinlich die 8 Minuten, die Sie in 3. beobachten, wo die LDF-Nutzung ziemlich konstant bleibt.
Mustaccio
@mustaccio Ich würde dir zustimmen, aber die Artefakte zeigen in eine andere Richtung. Wenn das Rollback tatsächlich stattgefunden hat, muss die Protokolldateiverwendung auf eine kleinere Zahl zurückgesetzt werden. und nicht bei 99,3% bleiben, wenn die Fehlermeldung ausgelöst wird.
ToC
1
Ich glaube, Rollback nimmt Speicherplatz in Anspruch. Wenn das Protokoll während des Rollbacks voll wird, wird die Datenbank verdächtig. Es wird nicht weiter berührt. Dies sieht aus wie ein sofortiger Rollback, aber der Rollback wurde verschoben, bis Sie die Datenbank wieder online stellen können (wenn Speicherplatz verfügbar ist) .; Wenn das Protokoll voll wird, versucht SQL Server möglicherweise, durch Checkpointing Platz zu schaffen, was möglicherweise Spitzen in der E / A-Aktivität erklärt.
USR

Antworten:

1

Wie oben angegeben, bin ich nach weiteren Tests zu einem kalkulierten Ergebnis gekommen. Ich habe alle in einem Blogbeitrag zusammengefasst , aber ich werde einige Inhalte für die Nachwelt in diesen Beitrag kopieren.

Vermutung (basierend auf einigen Tests)

Derzeit habe ich keine klare Erklärung, warum dies so ist. Es folgen jedoch meine Schätzungen, die auf den Artefakten basieren, die während der Tests gesammelt wurden.

Rollback erfolgt in beiden Szenarien. Einer ist explizites Rollback (Benutzer drückt auf Abbrechen), der andere ist implizit (SQL Server trifft diese Entscheidung intern).

In beiden Szenarien ist der Datenverkehr zur Protokolldatei konsistent. Siehe die Bilder unten:

Szenario 1:

Szenario 1:

Szenario 2:

Szenario 2

  • Ein Artefakt, das diese Denkweise verstärkt hat, ist die Erfassung von SQL Trace in beiden Szenarien.

    • Szenario 1 ist offensichtlich, auch wenn wir auf "Abbrechen" klicken, wird es zurückgesetzt.
    • In Szenario 2 wird die Fehlermeldung angezeigt, nachdem implizit ein Rollback durchgeführt wurde. In SQL Trace sehen wir die Fehlermeldung "Das Transaktionsprotokoll für die Datenbank 'SampleDB' ist voll", lange bevor die Meldung auf dem Bildschirm angezeigt wird. Ich vermute also, dass Rollbacks in beiden Szenarien stattfinden, aber die Fehlermeldung lautet, dass Szenario 2 nach erfolgreicher und vollständiger Durchführung des Rollbacks angezeigt wird.
  • Szenario 2 scheint im weiteren Verlauf länger zu dauern, sodass das Rollback länger dauert.

Unerklärtes Verhalten:

  • Warum variiert die Verwendung der Protokolldateien so stark?
    • Es steigt auf 90%, dann auf 85%, dann auf 99% und schwebt dort lange. Ich sehe es mehrmals so auf und ab gehen: 99,2%, 99,8%, 99,1%, 99,7%. Warum passiert das?
    • Eine mögliche Erklärung ist, dass es möglicherweise einen Hintergrundprozess gibt (so etwas wie Log Flush), der alle paar Minuten die Protokolldatei bereinigt. Und bei jedem Start werden einige Einträge gelöscht, sodass mehr Speicherplatz verfügbar ist.

Anregungen zur besseren Erklärung dieses Verhaltens sind willkommen.

ToC
quelle
2
Nach Rücksprache mit Paul Randal hat er bestätigt, dass Sie zu dem richtigen Ergebnis gekommen sind - das Rollback ist in beiden Fällen das gleiche.
Paul White setzt Monica wieder ein
0

Ich habe das folgende Experiment ausprobiert und ähnliche Ergebnisse erhalten. In beiden Fällen zeigt fn_dblog (), dass ein Rollback stattfindet, und dies scheint in Szenario 2 schneller zu geschehen als in Szenario 1.

Übrigens habe ich sowohl MDF als auch LDF auf derselben externen Festplatte (USB 2.0) abgelegt.

Meine anfängliche Schlussfolgerung ist, dass es in diesem Fall keinen Unterschied in der Funktionsweise des Rollbacks gibt, und wahrscheinlich ist jeder offensichtliche Geschwindigkeitsunterschied auf das E / A-Subsystem zurückzuführen. Das ist im Moment nur meine Arbeitshypothese.

Szenario 1:

  • Erstellen Sie eine Datenbank mit einer Protokolldatei, die bei 1 MB beginnt, in 4 MB großen Blöcken wächst und eine maximale Größe von 100 MB hat.
  • Öffnen Sie eine explizite Transaktion, führen Sie sie 10 Sekunden lang aus und brechen Sie sie dann in SSMS manuell ab
  • Sehen Sie sich die Anzahl der fn_dblog () und die Größe der Protokollreserve an und überprüfen Sie DBCC SQLPERF (LOGSPACE).

Szenario 2:

  • Erstellen Sie eine Datenbank mit einer Protokolldatei, die bei 1 MB beginnt, in 4 MB großen Blöcken wächst und eine maximale Größe von 100 MB hat.
  • Öffnen Sie eine explizite Transaktion und führen Sie sie aus, bis der vollständige Fehler im Protokoll angezeigt wird
  • Sehen Sie sich die Anzahl der fn_dblog () und die Größe der Protokollreserve an und überprüfen Sie DBCC SQLPERF (LOGSPACE).

Ergebnisse der Leistungsüberwachung:

Szenario 1: ***Szenario 1***

Szenario 2: *** Szenario 2 ***

Code:

USE [master];
GEHEN

IF DATABASEPROPERTYEX (N'SampleDB ', N'Version')> 0
START
    ALTER DATABASE [SampleDB] SET SINGLE_USER
        MIT ROLLBACK SOFORT;
    DROP DATABASE [SampleDB];
ENDE;
GEHEN

CREATE DATABASE [SampleDB] ON PRIMARY 
( 
      NAME = N'SampleDB '
    , FILENAME = N'E: \ data \ SampleDB.mdf ' 
    , GRÖSSE = 3 MB 
    , FILEGROWTH = 1 MB 
)
EINLOGGEN 
( 
      NAME = N'SampleDB_log '
    , FILENAME = N'E: \ data \ SampleDB_log.ldf '
    , GRÖSSE = 1 MB 
    , MAXSIZE = 100 MB 
    , FILEGROWTH = 4 MB 
);
GEHEN

USE [SampleDB];
GEHEN

- Fügen Sie eine Tabelle hinzu
CREATE TABLE dbo.test
(
    c1 CHAR (8000) NOT NULL DEFAULT REPLICATE ('a', 8000)
) ON [PRIMARY];
GEHEN

- Stellen Sie sicher, dass es sich nicht um ein pseudo-einfaches Wiederherstellungsmodell handelt
BACKUP DATABASE SampleDB
TO DISK = 'NUL';
GEHEN

- Sichern Sie die Protokolldatei
BACKUP LOG SampleDB
TO DISK = 'NUL';
GEHEN

- Überprüfen Sie den verwendeten Protokollspeicherplatz
DBCC SQLPERF (LOGSPACE);
GEHEN

- Wie viele Datensätze sind mit fn_dblog () sichtbar?
SELECT * FROM fn_dblog (NULL, NULL); - Gegen 9 in meinem Fall

/ ***********************************
             SZENARIO 1
*********************************** /
- Öffnen Sie eine neue Transaktion und setzen Sie sie zurück
TRANSAKTION BEGINNEN

    INSERT INTO dbo.test DEFAULT VALUES;
    GO 10000 - Lassen Sie das Programm 10 Sekunden lang laufen und klicken Sie dann im SSMS-Abfragefenster auf Abbrechen

    - Brechen Sie die Transaktion ab
    - Der Vorgang sollte einige Sekunden dauern


- Sie müssen die Transaktion nicht zurücksetzen, da der Abbruch dies bereits für Sie erledigt hat.
-- Probier es einfach. Sie erhalten diesen Fehler
- Nachricht 3903, Ebene 16, Status 1, Zeile 1
- Die Anforderung ROLLBACK TRANSACTION hat keine entsprechende BEGIN TRANSACTION.
ROLLBACK-TRANSAKTION;

- Was ist der verwendete Protokollspeicherplatz? Über 100%.
DBCC SQLPERF (LOGSPACE);
GEHEN

- Wie viele Datensätze sind mit fn_dblog () sichtbar?
WÄHLEN * 
FROM fn_dblog (NULL, NULL); - Ungefähr 91.926 in meinem Fall

- Gesamte Log-Reserve von fn_dblog () angezeigt?
SELECT SUM ([Log Reserve]) AS [Gesamte Log Reserve]
FROM fn_dblog (NULL, NULL); - Ungefähr 88,72 MB


/ ***********************************
             SZENARIO 2
*********************************** /
- Die DB wegblasen und von vorne anfangen
USE [master];
GEHEN

IF DATABASEPROPERTYEX (N'SampleDB ', N'Version')> 0
START
    ALTER DATABASE [SampleDB] SET SINGLE_USER
        MIT ROLLBACK SOFORT;
    DROP DATABASE [SampleDB];
ENDE;
GEHEN

CREATE DATABASE [SampleDB] ON PRIMARY 
( 
      NAME = N'SampleDB '
    , FILENAME = N'E: \ data \ SampleDB.mdf ' 
    , GRÖSSE = 3 MB 
    , FILEGROWTH = 1 MB 
)
EINLOGGEN 
( 
      NAME = N'SampleDB_log '
    , FILENAME = N'E: \ data \ SampleDB_log.ldf '
    , GRÖSSE = 1 MB 
    , MAXSIZE = 100 MB 
    , FILEGROWTH = 4 MB 
);
GEHEN

USE [SampleDB];
GEHEN

- Fügen Sie eine Tabelle hinzu
CREATE TABLE dbo.test
(
    c1 CHAR (8000) NOT NULL DEFAULT REPLICATE ('a', 8000)
) ON [PRIMARY];
GEHEN

- Stellen Sie sicher, dass es sich nicht um ein pseudo-einfaches Wiederherstellungsmodell handelt
BACKUP DATABASE SampleDB
TO DISK = 'NUL';
GEHEN

- Sichern Sie die Protokolldatei
BACKUP LOG SampleDB
TO DISK = 'NUL';
GEHEN

- Nun wollen wir die Protokolldatei innerhalb unserer Transaktion sprengen
TRANSAKTION BEGINNEN
    INSERT INTO dbo.test DEFAULT VALUES;
    GO 10000

- Das Rollback wird niemals ausgelöst. Versuch es. Sie erhalten eine Fehlermeldung.
- Nachricht 3903, Ebene 16, Status 1, Zeile 1
- Die Anforderung ROLLBACK TRANSACTION hat keine entsprechende BEGIN TRANSACTION.
ROLLBACK-TRANSAKTION;

- Ist die Protokolldatei zu 100% voll? 
DBCC SQLPERF (LOGSPACE);

- Wie viele Datensätze sind mit fn_dblog () sichtbar?
WÄHLEN * 
FROM fn_dblog (NULL, NULL); - Ungefähr 91.926 in meinem Fall
GEHEN

- Gesamte Log-Reserve von fn_dblog () angezeigt?
SELECT SUM ([Log Reserve]) AS [Gesamte Log Reserve]
FROM fn_dblog (NULL, NULL); - 88,72 MB
GEHEN
outwire
quelle
Vielen Dank für die ausführlichen Tests. Nachdem ich weitere Tests durchgeführt hatte, kam ich zu einem ähnlichen Ergebnis. Also schrieb ich einen Blog- Beitrag. Für mich dauert das Rollback von Szenario 2 länger, da der Arbeitsaufwand in Szenario 2, bevor SQL Server erkennt, dass ein Rollback erforderlich ist,
Uhr