Ogni database di SQL Server contiene uno o più file di registro delle transazioni oltre ai file di dati. I file di registro registrano tutte le transazioni e le modifiche al database apportate da ciascuno di essi.
Questo articolo è incentrato sul registro delle transazioni e sul modo in cui SQL Server registra le modifiche ai dati per utilizzare i dati per il ripristino in modo anomalo del database.
Introduzione al file di registro delle transazioni di SQL Server
Come ricordiamo, ogni transazione è “tutto o niente”. Se una parte della transazione ha esito negativo, l'intera transazione ha esito negativo e lo stato del database rimane invariato.
SQL Server archivia un record di ogni transazione eseguita sul database nel file di registro. Se qualche emergenza comporta l'arresto di SQL Server, utilizza un registro delle transazioni per ripristinare il database in uno stato coerente con l'integrità dei dati.
Dopo il riavvio, SQL Server avvia il processo di ripristino dell'arresto anomalo. Legge il file di registro delle transazioni per garantire che tutti i dati validi siano archiviati nei file di dati e che le transazioni non vincolate vengano annullate.
Durante il normale funzionamento, SQL Server utilizza anche il registro delle transazioni. Le informazioni contenute nel file sono necessarie per identificare cosa deve fare SQL Server quando si esegue il rollback di una transazione a causa di un errore o di un'istruzione ROLLBACK specificata dall'utente.
Come SQL Server utilizza il registro delle transazioni
Il registro delle transazioni è un file fisico con estensione LDF . SQL Server lo crea automaticamente per qualsiasi nuovo database insieme al file di dati primario (.MDF ) che memorizza gli oggetti del database ei dati stessi.
Ogni volta che il codice T-SQL modifica un oggetto di database o i dati in esso contenuti, i dettagli della modifica vengono registrati come record di registro nel file di registro delle transazioni.
Il record di log contiene le informazioni di una specifica modifica apportata al database (ad esempio, inserire una singola riga). Pertanto, avremo una serie di record di registro per descrivere completamente gli effetti di una singola transazione.
Architettura del registro delle transazioni
Numeri di sequenza del registro
Un record di registro ha un numero di sequenza di registro univoco e autoincrementante (LSN ), che ci consente di trovare questo record nel registro delle transazioni. LSN descrive la modifica dei dati e contiene le seguenti informazioni:
- l'operazione e la riga interessata
- la vecchia e la nuova versione dei dati
- la transazione che ha eseguito la modifica
LSN è composto da tre numeri:
LSN =
Ciascuna pagina del 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.
Quando viene eseguito il ripristino in caso di arresto anomalo, confronta gli LSN dei record di registro per le transazioni confermate o non vincolate con gli LSN nelle pagine dei file di dati per determinare se è necessario eseguire operazioni di ripristino o annullamento su quei record di registro particolari.
Quando crei un database, è buona norma specificare la dimensione del log delle transazioni . In caso contrario, SQL Server creerà automaticamente il registro delle transazioni con la dimensione predefinita.
La dimensione predefinita del registro delle transazioni di un nuovo database è il maggiore di 0,5 MB o 25% della dimensione totale di tutti i file di dati creati nella stessa istruzione CREATE DATABASE.
Devi stare molto attento perché le nuove parti del registro delle transazioni sono sempre inizializzate da zero . Se si dispone dell'istruzione CREATE DATABASE senza specificare la dimensione del file di registro e si crea, ad esempio, un database di 1 TB, SQL Server creerà il registro delle transazioni da 250 GB.
Poiché il registro deve essere inizializzato da zero, non utilizza l'inizializzazione del file istantaneo. Questa funzionalità è stata aggiunta in SQL Server 2005 per consentire la creazione o l'espansione quasi istantanea dei file di dati.
Possiamo vedere cosa sta succedendo quando CREA DATABASE:si verifica l'inizializzazione zero del nostro registro utilizzando trace flag 3004 che stampa messaggi sull'inizializzazione zero e traccia flag 3605 che consente di stampare quei messaggi di registro tramite il flag di traccia 3004.
La seguente demo mostra come puoi vedere l'azzeramento del file di registro in corso.
1. Esegui il seguente script per assicurarti di non avere un database chiamato DBTest2014
USE master;
GO
IF DATABASEPROPERTY(N'DBTest2014', N'Version')>0
BEGIN
ALTER DATABASE DBTest2014 SET SINGLE_USER
WITH ROLLBACK IMMEDIATE;
DROP DATABASE DBTest2014;
END
GO
2. Abilita i flag di traccia per guardare l'inizializzazione zero
DBCC TRACEON (3605, 3004, -1);
GO
3. Flush the error log
EXEC sp_cycle_errorlog;
GO
3. Crea un database
CREATE DATABASE DBTest2014 ON PRIMARY (
NAME = N'DBTest2014',
FILENAME = N'D:\DBTest2014_data.mdf')
LOG ON (
NAME= N'DBTest2014_log',
FILENAME= N'D:\DBTest2014_log.ldf',
SIZE = 10MB,
FILEGROWTH = 10 MB);
GO
4. Leggere il file di registro degli errori
EXEC sys.xp_readerrorlog;
GO
File di registro virtuali
Il registro delle transazioni è suddiviso internamente in una serie di blocchi chiamati file di registro virtuali (VLF ) per semplificare la gestione.
Ogni volta che viene creato un registro delle transazioni, fornisce un certo numero di VLF. I VLF appena creati sono inattivi e inutilizzati. Un VLF attivo non può essere riutilizzato finché non viene reso inattivo dalla cancellazione del registro.
Tuttavia, c'è un'eccezione:il primo VLF in un nuovo database è sempre attivo perché qualsiasi registro delle transazioni deve avere almeno un VLF attivo.
Ogni file di registro ha anche una pagina di intestazione del file che richiede 8KB all'inizio del file di registro delle transazioni. La pagina di intestazione del file memorizza i metadati relativi al file, ad esempio le dimensioni e le impostazioni di crescita automatica.
Il numero e la dimensione dei VLF in una nuova parte del registro delle transazioni sono determinati da SQL Server. È impossibile configurarlo.
Se la nuova dimensione aggiunta è:
- <1 MB è irrilevante per la discussione
- <64 MB ci saranno 4 nuovi VLF (ciascuno 1/4 della dimensione di crescita)
- Da 64 MB a 1 GB ci saranno 8 nuovi VLF (ciascuno 1/8 della dimensione di crescita)
- > 1 GB ci saranno 16 nuovi VLF (ciascuno 1/16 della dimensione di crescita)
Questo vale per il registro delle transazioni creato inizialmente e per ogni crescita manuale o automatica che si verifica. Conoscere la formula del numero potenziale di VLF e la loro dimensione potenziale, aiuta a gestire il registro. Troppi o troppi VLF possono causare problemi di prestazioni con le operazioni del registro delle transazioni.
Numero sequenza VLF
Ogni VLF ha un numero di sequenza per identificare in modo univoco il VLF all'interno del registro delle transazioni. Il numero di sequenza aumenta di uno ogni volta che il sistema di gestione dei log attiva il VLF successivo. La catena dei numeri di sequenza fornisce l'insieme di VLF attualmente attivo.
L'inizio della parte attiva del registro delle transazioni inizia con un VLF che ha il numero di sequenza più basso ed è ancora attivo. I VLF inattivi hanno numeri di sequenza, ma non fanno parte della parte attiva del registro.
La parte attiva del registro contiene record di registro richiesti per qualche motivo da SQL Server.
Quando crei un nuovo database per la prima volta, i numeri di sequenza VLF non iniziano con 1. Iniziano con il numero di sequenza VLF più alto nel registro delle transazioni del database del modello, più 1 . È impossibile esaurire i numeri di sequenza VLF. SQL Server dispone di un codice che forzerà l'arresto dell'istanza se un numero di sequenza VLF va a capo fino a zero (se il numero di sequenza VLF successivo è inferiore a quello precedente).
VLF e blocchi log
All'interno dei VLF, ci sono blocchi di log di dimensioni variabili. La dimensione minima del blocco di log è 512 byte e blocchi di log crescono fino a una dimensione massima di 60 KB . La dimensione viene impostata quando si verifica uno dei seguenti casi:
- Una transazione genera un record di registro per confermare di terminare l'interruzione di una transazione
- La dimensione del blocco di registro raggiunge i 60 KB senza che una transazione venga confermata o interrotta
Ci sono record di registro all'interno di un blocco di registro (colorato nel diagramma). Anche i record di registro hanno dimensioni variabili. Il diagramma mostra che i record di registro di più transazioni simultanee possono esistere all'interno dello stesso blocco di registro. I record di registro vengono archiviati nell'ordine scritto in modo simile a un file di pagina dati.
Ogni VLF contiene un'intestazione VLF con le seguenti informazioni:
- Se il VLF è attivo o meno.
- Il numero di sequenza del registro quando è stato creato il VLF.
- I bit di parità correnti per tutti i blocchi da 512 byte nel VLF.
I bit di parità iniziano a 64 per la prima volta in assoluto di utilizzo VLF. Se VLF diventa inattivo, ma viene ulteriormente riattivato, i bit di parità diventeranno 128. Questi vengono utilizzati durante il ripristino del crash.
Esame dei dettagli del registro delle transazioni – DBCC LOGINFO
L'unico modo per esaminare la struttura del registro delle transazioni è utilizzare il DBCC LOGINFO non documentato comando. La sintassi del comando è:
DBCC LOGINFO [({'dbname | dbid'})]
Se non specifichi dbname e dbid , ti scaricherà il contenuto del registro per il database corrente.
Il risultato è una riga per ogni VLF presente nel registro delle transazioni per quel database. I campi restituiti sono:
- RecoveryUnitId — aggiunto in SQL Server 2012 ma attualmente inutilizzato
- IDFile — ID del file di registro delle transazioni all'interno di un database.
- Dimensione file — Dimensioni VLF in byte.
- StartOffset — offset iniziale del VLF nel file di registro delle transazioni, in byte
- FSeqNo — Il numero di sequenza VLF
- Stato — Se il VLF è attivo o meno (0 =inattivo, 2 =attivo, 1 – non è utilizzato)
- Parità — bit di parità corrente (64 o 128, o 0 se il VLF non è mai stato attivo)
- CreateLSN — LSN quando è stato creato il VLF (0 =il VLF è stato creato quando è stato inizialmente creato il file di registro delle transazioni). Tutti gli altri VLF aggiunti dopo la creazione iniziale del file di registro delle transazioni avranno CreateLSN diverso da zero.
Possiamo eseguire il seguente comando per DBTest2014 database, che abbiamo creato in precedenza:
DBCC LOGINFO (N'DBTest2014');
GO
Guarda il risultato:
DBCC SQLPERF (LOGSPACE)
L'unico modo in Transact-SQL per esaminare la quantità del log utilizzato è DBCC SQLPERF. La sintassi del comando è:
DBCC SQLPERF
(
[ LOGSPACE ]
|
[ "sys.dm_os_latch_stats" , CLEAR ]
|
[ "sys.dm_os_wait_stats" , CLEAR ]
)
[WITH NO_INFOMSGS ]
Il comando restituisce un set di risultati con una riga per database:
- Nome database
- Dimensione registro (MB)
- Spazio log utilizzato (%)
- Stato:sempre impostato a zero
Nel mio ambiente, il seguente comando:
DBCC SQLPERF (LOGSPACE);
GO
Restituisce il seguente risultato:
Nel prossimo articolo esamineremo i record di registro.