Varje SQL Server-databas innehåller en eller flera transaktionsloggfiler förutom datafiler. Loggfiler registrerar alla transaktioner och databasändringar gjorda av var och en av dem.
Den här artikeln fokuserar på transaktionsloggen och hur SQL Server loggar dataändringar för att använda data för databaskraschåterställning.
Introduktion till SQL Server Transaction Log File
Som vi minns är varje transaktion "allt eller inget". Om en del av transaktionen misslyckas, misslyckas hela transaktionen och databastillståndet förblir oförändrat.
SQL Server lagrar en post över varje transaktion som utförs på databasen i loggfilen. Om någon katastrof medför avstängning av SQL Server, använder den en transaktionslogg för att återställa databasen till ett konsekvent tillstånd med dataintegritet.
Efter omstarten startar SQL Server kraschåterställningsprocessen. Den läser transaktionsloggfilen för att säkerställa att all giltig data lagras i datafilerna och att icke-åtagande transaktioner rullas tillbaka.
Under normal drift använder SQL Server också transaktionsloggen. Informationen som finns i filen är nödvändig för att identifiera vad SQL Server behöver göra när en transaktion rullar tillbaka på grund av antingen ett fel eller en användarspecificerad ROLLBACK-sats.
Hur SQL Server använder transaktionsloggen
Transaktionsloggen är en fysisk fil med tillägget LDF . SQL Server skapar den automatiskt för alla nya databaser tillsammans med den primära datafilen (.MDF ) som lagrar databasobjekten och själva data.
Närhelst T-SQL-koden ändrar ett databasobjekt eller de data som det innehåller, registreras detaljer om ändringen som en loggpost i transaktionsloggfilen.
Loggposten innehåller information om en specifik ändring som gjorts i databasen (t.ex. infoga en enda rad). Därför kommer vi att ha en serie loggposter för att fullständigt beskriva effekterna av en enskild transaktion.
Transaktionsloggarkitektur
Loggsekvensnummer
En loggpost har ett unikt, automatiskt ökande loggsekvensnummer (LSN ), som gör att vi kan hitta denna post i transaktionsloggen. LSN beskriver dataändringen och innehåller följande information:
- åtgärden och den berörda raden
- gamla och nya versioner av data
- transaktionen som utförde ändringen
LSN består av tre nummer:
LSN =
Varje datafilsida har ett LSN i sidhuvudet som identifierar den senaste loggposten vars ändring återspeglas på sidan. Detta är avgörande för återställning av kraschar.
När kraschåterställningen körs, jämför den LSN:erna för loggposter för begångna eller oengagerade transaktioner med LSN:er på datafilsidor för att avgöra om det finns någon göra om eller ångra att göra på just de loggposterna.
När du skapar en databas är en god praxis att specificera storleken på transaktionsloggen . Om du inte gör detta kommer SQL Server automatiskt att skapa transaktionsloggen med standardstorleken.
Transaktionsloggens standardstorlek av en ny databas är den största av 0,5 MB eller 25 % av den totala storleken på alla datafiler som skapats i samma CREATE DATABASE-sats.
Du måste vara mycket försiktig eftersom nya delar av transaktionsloggen alltid nollinitieras . Om du har CREATE DATABASE-satsen utan att ange loggfilens storlek, och du skapar till exempel en databas på 1 TB, kommer SQL Server att skapa transaktionsloggen på 250 GB.
Eftersom loggen måste nollinitieras, använder den inte den omedelbara filinitieringen. Denna funktion lades till i SQL Server 2005 för att tillåta att datafilerna kan skapas eller växa nästan omedelbart.
Vi kan se vad som händer när vi SKAPAR DATABAS – nollinitieringen sker av vår logg med spårningsflagga 3004 som skriver ut meddelanden om nollinitiering och spårningsflagga 3605 som gör det möjligt att skriva ut dessa loggmeddelanden med spårningsflaggan 3004.
Följande demo visar hur du kan se att loggfilen nollställs.
1. Kör följande skript för att se till att vi inte har en databas som heter 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. Aktivera spårningsflaggor för att se nollinitiering
DBCC TRACEON (3605, 3004, -1);
GO
3. Flush the error log
EXEC sp_cycle_errorlog;
GO
3. Skapa en databas
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. Läs felloggfilen
EXEC sys.xp_readerrorlog;
GO
Virtuella loggfiler
Transaktionsloggen delas upp internt i en serie bitar som kallas virtuella loggfiler (VLF:er ) för att förenkla hanteringen.
Närhelst en transaktionslogg skapas ger den ett visst antal VLF:er. Nyskapade VLF:er är inaktiva och oanvända. En aktiv VLF kan inte återanvändas förrän den görs inaktiv genom loggrensning.
Det finns dock ett undantag – den första VLF i en ny databas är alltid aktiv eftersom varje transaktionslogg måste ha minst en aktiv VLF.
Varje loggfil har också en filhuvudsida som tar 8KB i början av transaktionsloggfilen. Filhuvudsidan lagrar metadata om filen såsom storlek och inställningar för automatisk tillväxt.
Antalet och storleken på VLF i en ny del av transaktionsloggen bestäms av SQL Server. Det är omöjligt att konfigurera det.
Om den nyligen tillagda storleken är:
- <1MB är irrelevant för diskussion
- <64 MB kommer det att finnas 4 nya VLF:er (var 1/4 av tillväxtstorleken)
- 64 MB till 1 GB kommer det att finnas 8 nya VLF:er (vardera 1/8 av tillväxtstorleken)
- > 1 GB kommer det att finnas 16 nya VLF:er (var 1/16 av tillväxtstorleken)
Detta gäller den initialt skapade transaktionsloggen och för varje manuell eller automatisk tillväxt som sker. När du känner till formeln för det potentiella antalet VLF och deras potentiella storlek, hjälper det att hantera loggen. För få eller för många VLF kan orsaka prestandaproblem med transaktionsloggoperationer.
VLF-sekvensnummer
Varje VLF har ett sekvensnummer för att unikt identifiera VLF i transaktionsloggen. Sekvensnumret ökar med ett varje gång logghanteringssystemet aktiverar nästa VLF. Kedjan av sekvensnumren ger den för närvarande aktiva uppsättningen av VLF.
Starten av transaktionsloggens aktiva del börjar med en VLF som har det lägsta sekvensnumret och som fortfarande är aktiv. Inaktiva VLF:er har sekvensnummer, men de är inte en del av den loggaktiva delen.
Den aktiva delen av loggen har loggposter som av någon anledning krävs av SQL Server.
När du först skapar en ny databas kommer VLF-sekvensnumren inte att börja på 1. De börjar med det högsta VLF-sekvensnumret som finns i modellens transaktionslogg, plus 1 . Det är omöjligt att få slut på VLF-sekvensnummer. SQL Server har kod som kommer att tvinga instansen att stängas av om ett VLF-sekvensnummer någonsin går runt till noll (om nästa VLF-sekvensnummer är mindre än det föregående).
VLF och loggblock
Inom VLF:er finns stockblock av varierande storlek. Minsta storlek på loggblocket är 512 byte och loggblock växer upp till en maximal storlek på 60 KB . Storleken ställs in när något av följande fall inträffar:
- En transaktion genererar en loggpost för att slutföra avbrytande av en transaktion
- Storleken på loggblocket når 60 kB utan att en transaktion genomförs eller avbryts
Det finns loggposter i ett loggblock (färgat på diagrammet). Loggposter har också varierande storlek. Diagrammet visar att loggposter från flera samtidiga transaktioner kan finnas inom samma loggblock. Loggposterna lagras i den ordning som skrivs på samma sätt som en datasidafil.
Varje VLF innehåller en VLF-rubrik med följande information:
- Oavsett om VLF är aktiv eller inte.
- Loggsekvensnumret när VLF skapades.
- De aktuella paritetsbitarna för alla 512-byte block i VLF.
Paritetsbitarna börjar vid 64 för första gången VLF används. Om VLF blir inaktivt, men återaktiveras ytterligare, blir paritetsbitarna 128. Dessa används under kraschåterställning.
Undersöker transaktionsloggdetaljer – DBCC LOGINFO
Det enda sättet att titta på transaktionsloggstrukturen är att använda den odokumenterade DBCC LOGINFO kommando. Syntaxen för kommandot är:
DBCC LOGINFO [({'dbname | dbid'})]
Om du inte anger dbname och dbid , kommer det att dumpa logginnehållet för den aktuella databasen.
Resultatet är en rad för varje VLF som finns i transaktionsloggen för den databasen. De returnerade fälten är:
- RecoveryUnitId — lagt till i SQL Server 2012 men för närvarande oanvänd
- Fil-ID — transaktionsloggfil-ID i en databas.
- Filstorlek — VLF-storlek i byte.
- StartOffset — startoffset för VLF i transaktionsloggfilen, i byte
- FSeqNo — VLF-sekvensnumret
- Status — Om VLF är aktiv eller inte (0 =inaktiv, 2 =aktiv, 1 – används inte)
- Paritet — nuvarande paritetsbitar (64 eller 128, eller 0 om VLF aldrig har varit aktiv)
- SkapaLSN — LSN när VLF skapades (0 =VLF skapades när transaktionsloggfilen ursprungligen skapades). Alla andra VLF:er som läggs till efter den första skapandet av transaktionsloggfilen kommer att ha CreateLSN som inte är noll.
Vi kan köra följande kommando för DBTest2014 databas, som vi har skapat tidigare:
DBCC LOGINFO (N'DBTest2014');
GO
Se resultatet:
DBCC SQLPERF (LOGSPACE)
Det enda sättet i Transact-SQL att undersöka mängden logg som används är DBCC SQLPERF. Syntaxen för kommandot är:
DBCC SQLPERF
(
[ LOGSPACE ]
|
[ "sys.dm_os_latch_stats" , CLEAR ]
|
[ "sys.dm_os_wait_stats" , CLEAR ]
)
[WITH NO_INFOMSGS ]
Kommandot returnerar en resultatuppsättning med en rad per databas:
- Databasnamn
- Loggstorlek (MB)
- Använt loggutrymme (%)
- Status:alltid noll
I min miljö, följande kommando:
DBCC SQLPERF (LOGSPACE);
GO
Returnerar följande resultat:
I nästa artikel kommer vi att undersöka loggposter.