Zeichnet das SQL Server-Protokoll nicht festgeschriebene Vorgänge auf?

12

Ich sehe oft Anweisungen wie SQL Server Logs, die jede Transaktion und jeden Vorgang aufzeichnen.

Aber ich bin verwirrt über das, was passiert , wenn eine Transaktion schließlich wird gerollt zurück .

Sprich eine explizite Transaktion hat drei Aussagen: statement A, statement B, statement C, und schließlich ein rollback statement D.

Sagen Sie nun, wenn die Ausführung das nicht erreicht hat rollback statement D, werden die Änderungen, die von resultieren statements A through C, im SQL Server-Protokoll aufgezeichnet?

Verständnis 1 :

Die Anweisungen A bis D werden alle aufgezeichnet. SQL Server zeichnet alles auf, egal was passiert.

Grundlegendes zu 2 : Änderungen werden nur irgendwo im Speicher gespeichert und nur aufgezeichnet, um zu protokollieren, wenn SQL Server eine commitAnweisung sieht . Wenn sich herausstellt, dass es sich um eine rollbackAnweisung handelt, ignoriert SQL Server die Transaktion einfach. Es wird kein Protokoll geschrieben, da dies keinen Zweck erfüllt. Mit anderen Worten, protokolliert SQL Server , wenn eine ist Netto- Ergebnis vor und nach den Transaktionen.

Beides erscheint mir logisch, kann aber nicht richtig sein. Danke für jede Hilfe.

John Smith
quelle
Hallo, versuchen Sie [ systoolsgroup.com/sql-log-analyzer.html] (SQL Log Analyzer), um zu analysieren, was in der Protokolldatei vor sich geht. Sie können die kostenlose Version von SysTools SQL Log Analyzer ausprobieren, um nur eine Vorschau der SQL-Protokolldaten anzuzeigen . Ich hoffe, das funktioniert für Sie.
Rylan08

Antworten:

13

Verständnis 1 ist richtig. SQL Server zeichnet jeden Vorgang auf, der Daten im Transaktionsprotokoll ändert. Ein Rollback ist eine Datenänderung, die auch im Transaktionsprotokoll aufgezeichnet wird. Bei Ausführung von Anweisung A werden Daten in das Transaktionsprotokoll geschrieben und Daten im Transaktionsprotokoll reserviert, falls Anweisung A zurückgesetzt werden muss. Gleiches gilt für B und C. Wenn Sie die Transaktion zurücksetzen, werden weitere Informationen in das Protokoll geschrieben.

Es gibt viele Möglichkeiten, dies in Aktion zu sehen. Im Folgenden finden Sie eine kurze Demo. Hier ist die Abfrage, die ich verwenden werde, um zu sehen, was in das Protokoll geschrieben wurde:

SELECT 
  COUNT(*) transaction_count
, SUM(database_transaction_log_bytes_used) used_bytes
, SUM(database_transaction_log_bytes_reserved) reserved_bytes
FROM sys.dm_tran_database_transactions
where database_id = 10;

Mein Tisch:

create table TLOGDEMO (FLUFF VARCHAR(1000));

BEGIN TRANSACTION

Abfrage A verwendet minimale Protokollierung:

INSERT INTO TLOGDEMO WITH (TABLOCK)
SELECT REPLICATE('A', 1000)
FROM master..spt_values t1
CROSS JOIN master..spt_values t2;

Nach einer:

╔═══════════════════╦════════════╦════════════════╗
 transaction_count  used_bytes  reserved_bytes 
╠═══════════════════╬════════════╬════════════════╣
                 1    24006640       175429451 
╚═══════════════════╩════════════╩════════════════╝

Abfrage B verwendet keine minimale Protokollierung:

INSERT INTO TLOGDEMO
SELECT REPLICATE('B', 1000)
FROM master..spt_values t1
CROSS JOIN master..spt_values t2;

Nach B:

╔═══════════════════╦════════════╦════════════════╗
 transaction_count  used_bytes  reserved_bytes 
╠═══════════════════╬════════════╬════════════════╣
                 1  7352935708      1613986255 
╚═══════════════════╩════════════╩════════════════╝

Abfrage C ändert weniger Daten:

INSERT INTO TLOGDEMO
SELECT REPLICATE('C', 1000)
FROM master..spt_values c;

Nach C:

╔═══════════════════╦════════════╦════════════════╗
 transaction_count  used_bytes  reserved_bytes 
╠═══════════════════╬════════════╬════════════════╣
                 1  7355821748      1614545331 
╚═══════════════════╩════════════╩════════════════╝

Jetzt werde ich ein ausstellen ROLLBACKund die DMV abfragen, während das Rollback stattfindet. Unten finden Sie eine Tabelle mit einigen Schnappschüssen:

╔═══════════════════╦════════════╦════════════════╗
 transaction_count  used_bytes  reserved_bytes 
╠═══════════════════╬════════════╬════════════════╣
 1                  7393305528  1573797677     
 1                  7458767420  1502635737     
 1                  7682482356  1259440979     
 1                  7803881368  1127471233     
 ...                ...         ...            
╚═══════════════════╩════════════╩════════════════╝

Währenddessen nehmen die ROLLBACKverwendeten Bytes zu und die reservierte Anzahl von Bytes ab. Dies liegt daran, dass SQL Server den zuvor reservierten Speicherplatz verwendet, um die Transaktion rückgängig zu machen. Um die Transaktion rückgängig zu machen, müssen Daten geändert werden, damit mehr Daten in das Protokoll geschrieben werden.

Joe Obbish
quelle
8

Änderungen an Datenbanktabellen werden zuerst in die Protokolldatei und dann in die Tabellen selbst geschrieben, zuerst im Speicher und dann mit einem asynchronen Prozess CHECKPOINTauf die Festplatte. Dieser Mechanismus ist als WAL (Write-Ahead Logging) bekannt und allen relationalen Datenbanken gemeinsam.

Das Protokoll selbst wird zuerst in den Speicher (genau in den Protokollpuffer) und dann auf die Festplatte geschrieben, die Datenbanktabellen werden jedoch erst dann berührt, wenn das Protokoll auf die Festplatte geschrieben wurde.

Dieser Mechanismus ermöglicht sowohl das Rollback von festgeschriebenen Transaktionen als auch das Rollback von nicht festgeschriebenen Transaktionen während des Wiederherstellungsprozesses. In Bezug auf Ihr Beispiel hätte das RDBMS keine Möglichkeit, die Datenbank in einer konsistenten Form wiederherzustellen , wenn etwas Schlimmes danach passiert wäre statement Cund Sie commitanstelle von rollback(das können Sie nicht im Voraus wissen) ein hatten, ohne jeden Schritt in der Transaktion zu speichern Art und Weise und die Transaktion würde die D(Haltbarkeit) in nicht erfüllen ACID.

Wenn einige Operationen rückgängig gemacht , es ist die Datendatei, die die Nettoänderungen empfängt (über CHECKPOINT), nicht die Protokolldatei.

Spaghettidba
quelle
5

Verständnis 1 ist richtig und Spaghettidba und Joe haben gute Erklärungen.

Wenn Sie selbst testen möchten (bitte auf einer Testinstanz), können Sie das folgende Skript verwenden:

--create a database and table for testing
USE master
GO
CREATE DATABASE tranlogtest
GO
USE tranlogtest
GO
CREATE TABLE t1
(junk char(1))

CHECKPOINT
GO

BEGIN TRAN
INSERT t1 VALUES ('a')
INSERT t1 VALUES ('b')
INSERT t1 VALUES ('c')

ROLLBACK
INSERT t1 VALUES ('d')

SELECT *
FROM fn_dblog(NULL,NULL)

Sie werden feststellen, dass SQL Server alles aufzeichnet, auch die Schritte, die zum Rückgängigmachen von Vorgängen ausgeführt wurden.

Wald
quelle