Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

Registro delle transazioni di SQL Server — Parte 2

Questo è il secondo articolo della serie dedicata al log delle transazioni di SQL Server e alle sue specificità. Qui esamineremo i dettagli del record di registro.

Registri dei registri

I record di registro sono il fulcro dei meccanismi di registrazione e ripristino. Un record di registro descrive una singola modifica in un database. Pertanto, ogni modifica a un database ha un record di registro o record di registro che aiutano a descrivere quella particolare modifica. Sebbene non sia necessario comprendere i dettagli dei record di registro, per capire cosa sta succedendo con la registrazione e il ripristino, questi dettagli sono estremamente interessanti.

Il record di registro ha un numero di sequenza di registro univoco che abbiamo definito nel primo articolo. Il numero di sequenza del registro consente di trovare il record del registro nel registro delle transazioni. Inoltre, ogni pagina di file di dati ha un LSN nell'intestazione della pagina che identifica il record di registro più recente la cui modifica si riflette nella pagina. Questo è fondamentale per il ripristino in caso di arresto anomalo.

I record di registro per le transazioni simultanee vengono mescolati nel registro delle transazioni in base a quando si sono verificati nel tempo. I record di registro vengono archiviati in blocchi di registro nel pool di buffer finché non vengono scaricati su disco.

Non sono presenti operazioni non registrate nei database utente o di sistema. Tuttavia, esiste un'eccezione:in tempdb, le operazioni di archivio versioni e file di lavoro non vengono registrate. I record di registro non vengono mai spostati nel registro delle transazioni.

Cosa c'è all'interno di un registro?

Le informazioni in un record di registro ne consentono il ripristino (roll-forward) o l'annullamento (roll-back). Questa capacità di un record di registro è fondamentale per consentire il rollback delle transazioni e per il lavoro di ripristino. I record di registro contengono molti campi, a seconda del tipo di record di registro. Ci sono alcuni campi comuni a tutti i record, tra cui:

  • Il tipo di record di registro
    • Inizia la registrazione del registro delle transazioni
    • registrare il registro delle transazioni del commit
    • allocazione di una pagina modificando la bitmap di allocazione
    • inserimento di una riga
    • eliminazione di una riga
    • modifica di una riga
  • Il contesto del record di registro , se presente.
  • L'ID transazione di cui fa parte il record di registro se del caso. La maggior parte dei record di registro fa parte delle transazioni.
  • La lunghezza del record di registro . I record di registro di solito hanno una dimensione fissa e quindi, a seconda della quantità di dati presenti nel record di registro, ci sarà anche una parte variabile.
  • L'LSN del record di registro precedente nella stessa transazione . Se c'è. L'LSN è essenzialmente un puntatore al record del registro delle transazioni precedente che è stato generato da quella particolare transazione. Questa catena degli LSN precedenti consente il rollback di quella particolare transazione, poiché il rollback viene eseguito nell'ordine inverso, a partire dal record di registro più recente.
  • La quantità di spazio di registro riservato nel caso in cui il record di registro debba essere annullato.

Prenotazione spazio log

Ogni record di registro generato nella parte forward di una transazione deve riservare spazio libero nel registro delle transazioni per consentire il rollback del record di registro, senza che il registro delle transazioni debba crescere.

Il meccanismo di prenotazione dello spazio di registro è molto conservativo, riservando sempre spazio sufficiente e di solito di più, nel caso si verifichi una situazione imprevista. Ad esempio, un aggiornamento o un'eliminazione su una tabella compressa riserverà più spazio rispetto a un aggiornamento simile o un'eliminazione su una tabella non compressa. Ciò accade perché il rollback dell'aggiornamento sulla tabella compressa potrebbe dover far fronte al fatto che la riga aggiornata non si trova più su una pagina compressa e quindi dovrebbe scrivere colonne a larghezza intera nel record di registro anziché dati compressi.

Tipi di record di registro

Esistono molti tipi di record di registro, inclusi:

  • LOP_FORMAT_PAGE L'operazione di formattazione della pagina del registro:è il punto in cui è stata formattata una pagina, il che significa che è stata creata l'intestazione. Il record di registro registrerà almeno l'intestazione della pagina e potenzialmente alcuni altri contenuti della pagina se la pagina è stata creata e compilata come parte di un'operazione come la compilazione o la ricostruzione di un indice)
  • LOP_MODIFY_ROW Questa operazione sta modificando una piccola parte di dati esistenti.
  • LOP_SET_BITS Questo record di registro si applica alle bitmap di allocazione.
  • LOP_INSERT_ROWS e LOP_DELETE_ROWS
  • LOP_SET_FREE_SPACE Si applica a PFS:l'allocazione della bitmap che tiene traccia degli stati di allocazione delle pagine.

Tutti i record di log che stanno per apportare una modifica a una pagina di dati o a una pagina di indice in un indice tabulare includono :

    • L'ID unità di allocazione
    • L'ID della pagina e l'ID dello slot del record sulla pagina, che è essenzialmente l'ID del record in base zero dei dati o del record dell'indice sulla pagina.
    • L'immagine residua o l'immagine precedente e successiva dei dati modificati. Potrebbero esserci più set di questi in un unico record di registro. Le immagini residue consentono il ripristino. Le immagini precedenti consentono l'annullamento.

Blocca registrazione

Alcuni record di registro includono una bitmap di cui sono stati mantenuti i blocchi quando si è verificata la modifica descritta. La bitmap contiene:

      • Conteggio del numero di serrature.
      • Che tipo e modalità di blocco, ad esempio un blocco di pagina in modalità X.
      • A cosa è dovuto il lucchetto

Durante il ripristino da arresto anomalo del sistema e i failover dei gruppi di mirroring/disponibilità del database, questi blocchi verranno acquisiti per tutti i record di registro che verranno annullati. Ciò consente la funzionalità di ripristino rapido in Enterprise Edition da SQL Server 2005 in poi.

Registra record nelle transazioni

Tutte le transazioni generano almeno tre record di log, sempre nella seguente sequenza:

        • LOP_BEGIN_XACT – include informazioni come SPID, nome della transazione e ora di inizio. Tutte le transazioni avviate da SQL Server hanno nomi per descrivere l'operazione (ad es. AllocFirstPage, DROPOBJ)
        • Altri record per la transazione.
        • LOP_COMMIT_XACT – se la transazione viene confermata.
        • LOP_ABORT_XACT – se la transazione viene annullata.

Entrambi includono l'ora di fine della transazione.
I record di registro in una transazione sono collegati tra loro all'indietro da LSN. Ciò significa che il record di registro successivo che viene generato per una transazione ha l'LSN del record di registro precedente che è stato generato per questa particolare transazione. Ciò consente il corretto rollback della transazione. Alcuni record di registro non sono affatto transazionali, tra cui:

        • Modifiche allo spazio libero PFS (impossibile riconciliare con altre transazioni)
        • Modifiche bitmap differenziali (solo modifica unidirezionale)

Esame dei record di registro

Esistono due modi per esaminare i record di registro. È possibile utilizzare la funzione DBCC LOGINFO, ma si consiglia di utilizzare la funzione con valori di tabella fn_dblog. Ha una sintassi estremamente semplice:

SELECT * FROM fn_dblog (startLSN, endLSN);
GO

È una funzione estremamente potente perché:

        • restituisce un set di risultati tabellare che può essere facilmente gestito.
        • consente di utilizzare predicati complessi.
        • esegue la scansione di tutto il registro delle transazioni nella parte attiva del registro, dall'inizio della transazione non vincolata più vecchia al record del registro più recente. Questo può essere ignorato usando il flag di traccia 2537

I campi startLSN e endLSN vengono generalmente passati come NULL
Ecco la demo:

USE DBTest2014
GO
 
SET NOCOUNT ON;
GO
 
--Set the SIMPLE recovery mode with no auto-stats
-- to avoid unwanted log records
ALTER DATABASE DBTest2014 SET RECOVERY SIMPLE;
ALTER DATABASE DBTest2014 SET AUTO_CREATE_STATISTICS OFF;
 
CREATE TABLE [TEST_TABLE] ([C1] INT, [C2] INT, [C3] INT);
 
INSERT INTO [TEST_TABLE] VALUES (1,1,1);
GO
 
--Clear out the log
CHECKPOINT;
GO
 
-- Implicit transaction
INSERT INTO [TEST_TABLE] VALUES (2,2,2);
GO
 
SELECT * FROM fn_dblog(null, null);
GO

Ecco il set di risultati abbreviato. In realtà fn_dblog restituisce una varietà di record diversi come Lunghezza record di registro, Bit flag, Riserva registro, AllocUnitId, PageID, SlotID, Pagina precedente LSN e altri.

Modifica del contenuto della riga

Le modifiche al registro vengono registrate in due modi:come LOP_MODIFY_ROW o LOP_MODIFY_COLUMNS disco. Indipendentemente dal metodo utilizzato, registrerà i byte che vengono effettivamente modificati. Ad esempio, la modifica di un valore INT da 1 a 24 registra solo un byte di modifica poiché gli altri tre zero byte non sono stati modificati. SQL Server utilizzerà un LOP_MODIFY_ROW registro se è presente una singola parte della riga in fase di aggiornamento. Una porzione è definita come segue:ogni colonna a lunghezza variabile della riga è una "porzione" e l'intera area a larghezza fissa della riga è una "porzione", anche se si stanno aggiornando più colonne, ma solo se i byte sono aggiornati sono 16 byte o meno distanziati nella riga.

LOP_MODIFY_ROW contiene:

  • Prima dell'immagine
  • Dopo l'immagine
  • Colonne chiave dell'indice, se applicabile
  • Blocca bitmap

LOP_MODIFY_COLUMNS contiene:

  • Matrice di offset prima e dopo
  • Matrice di lunghezza
  • Colonne chiave dell'indice, se applicabile
  • Blocca bitmap
  • Coppie di immagini prima e dopo

Registri del registro dei compensi

Questo è un tipo speciale di record di registro che viene utilizzato per facilitare il rollback di una transazione. Quando una transazione esegue il rollback, la modifica descritta da ciascun record di registro nella transazione deve essere annullata nel database. Il rollback inizia con il record di registro più recente per la transazione e segue i collegamenti LSN precedenti fino al record di registro LOP_BEGIN_XACT. Per ogni record di registro:

  • Esegui l'"anti-operazione" che annullerà gli effetti del record di registro
  • Genera un record di registro, contrassegnandolo come record di registro COMPENSAZIONE, poiché compensa il record di registro nella parte a termine della transazione.
  • L'LSN precedente del record di registro COMPENSATION punta al record di registro precedente a quello per cui sta compensando. In pratica fa sì che il record di registro non faccia più parte della catena di record di registro per la transazione.
  • Lo spazio di registro riservato per il record di registro viene rilasciato

I record del registro COMPENSAZIONE non possono essere annullati, solo rifatti.

Ripristino di una transazione

Ecco una rappresentazione grafica di cosa sta succedendo quando una transazione viene ripristinata:

Esaminiamo il seguente codice:

USE DBTest2014
GO
 
SET NOCOUNT ON;
GO
 
ALTER DATABASE DBTest2014 SET RECOVERY SIMPLE;
ALTER DATABASE DBTest2014 SET AUTO_CREATE_STATISTICS OFF;
 
CREATE TABLE [TEST_TABLE] ([C1] INT, [C2] INT, [C3] INT);
 
INSERT INTO [TEST_TABLE] VALUES (1,1,1);
INSERT INTO [TEST_TABLE] VALUES (2,2,2);
GO
--Clear out the log
CHECKPOINT;
GO
-- Explicit transaction to insert a new record
BEGIN TRAN;
INSERT INTO [TEST_TABLE] VALUES (3,3,3);
GO
 
SELECT * FROM fn_dblog(null, null);
GO
--Roll it back
ROLLBACK TRAN;
GO
 
SELECT * FROM fn_dblog(null, null);

Qui possiamo vedere un registro speciale con la descrizione “COMPENSAZIONE”

Se osserviamo l'LSN precedente, possiamo vedere che LOP_INSERT_ROWS che abbiamo fatto, rimanda a …0f40:0001 e questa è la transazione BEGIN perché la parte in avanti della transazione si collega al record di registro precedente. La LOP_DELETE_ROW il record del registro della compensazione non si collega a un record per il quale sta compensando, ma si collega ad esso (al record del registro delle transazioni BEGIN).

Quindi DELEDE ha compensato INSERT e lo ha rimosso dall'elenco dei record di registro. Il LOP_ABORT_XACT è il segnale che la transazione è terminata con il rollback. Inoltre, puoi vedere che LOP_ABORT_XACT rimanda a LOP_BEGIN_XACT.
Quando eseguiamo un record di registro di compensazione, la prenotazione dello spazio di registro diminuisce [-74]. Quindi in realtà sta restituendo dello spazio che era riservato per la parte forward della transazione (LOP_INSERT_ROWS [178]). Come puoi vedere, il sistema di prenotazione dello spazio di registro è molto conservativo:INSERT riserva più spazio di quello restituito da DELETE.

Rollback e backup differenziali

Se in un database è stato eseguito un backup completo, una transazione aggiorna 100.000 record ma viene eseguito il rollback della transazione, perché un backup differenziale esegue un backup di così tanti dati? Sicuramente il rollback della transazione significa che non è cambiato nulla? Il pezzo del puzzle che manca qui è che il rollback di una transazione non cancella tutte le modifiche apportate dalla transazione. Come abbiamo visto, il rollback deve generare record di log di compensazione, perché il rollback deve generare altre modifiche per compensare la parte in avanti della transazione. Le intestazioni di tutte le pagine interessate sono state modificate almeno due volte. Uno per aggiornare l'LSN della pagina per la parte forward della transazione e una per aggiornare l'LSN della pagina per la parte di rollback della transazione. In entrambi i casi, l'aggiornamento farà sì che l'estensione venga contrassegnata come modificata nella bitmap differenziale. Non importa quale fosse il cambiamento, solo che qualcosa nella misura in cui è cambiato. Non è possibile escludere queste estensioni dal backup differenziale.

Riepilogo

In questo articolo, abbiamo esaminato i record di registro. I record di registro sono il fulcro dei meccanismi di registrazione e ripristino. A ogni modifica in un database è associato un record di registro. Ogni record di registro descrive una piccola modifica. Una modifica di grandi dimensioni ha più record di registro all'interno di una singola transazione. Esistono molti tipi diversi di record di registro e ne abbiamo esaminati alcuni.

Il registro delle transazioni è un argomento essenzialmente vasto e un paio di articoli non sono sufficienti per svelare tutti i dettagli. Quindi, se vuoi ottenere informazioni più dettagliate, ti suggerisco di leggere il seguente libro:SQL Server Transaction Log Management di Tony Davis e Gail Shaw e questo articolo:Gestione del registro delle transazioni.

Leggi anche:

Immergiti nel registro delle transazioni di SQL Server — Parte 1
Immergiti nel registro delle transazioni di SQL Server — Parte 2