Elke SQL Server-database bevat naast gegevensbestanden een of meer transactielogbestanden. Logbestanden registreren alle transacties en databasewijzigingen die door elk van hen zijn gemaakt.
Dit artikel richt zich op het transactielogboek en hoe SQL Server gegevenswijzigingen registreert om de gegevens te gebruiken voor het herstel van de databasecrash.
Inleiding tot het SQL Server-transactielogboekbestand
Zoals we ons herinneren, is elke transactie "alles of niets". Als een deel van de transactie mislukt, mislukt de hele transactie en blijft de databasestatus ongewijzigd.
SQL Server slaat een record op van elke transactie die op de database is uitgevoerd in het logbestand. Als een ramp het afsluiten van SQL Server met zich meebrengt, gebruikt het een transactielogboek om de database te herstellen naar een consistente staat met gegevensintegriteit.
Na het opnieuw opstarten start SQL Server het crashherstelproces. Het leest het transactielogbestand om ervoor te zorgen dat alle geldige gegevens in de gegevensbestanden worden opgeslagen en dat niet-vastgelegde transacties worden teruggedraaid.
Tijdens de normale werking gebruikt SQL Server ook het transactielogboek. De informatie in het bestand is nodig om te bepalen wat SQL Server moet doen wanneer een transactie wordt teruggedraaid vanwege een fout of een door de gebruiker opgegeven ROLLBACK-instructie.
Hoe SQL Server het transactielogboek gebruikt
Het transactielogboek is een fysiek bestand met de extensie LDF . SQL Server maakt het automatisch aan voor elke nieuwe database samen met het primaire gegevensbestand (.MDF ) die de database-objecten en de gegevens zelf opslaat.
Telkens wanneer de T-SQL-code een databaseobject of de gegevens die het bevat, verandert, worden de details van de wijziging vastgelegd als een logrecord in het transactielogbestand.
Het logboekrecord bevat de informatie van een specifieke wijziging die in de database is aangebracht (bijvoorbeeld een enkele rij invoegen). Daarom hebben we een reeks logrecords om de effecten van een enkele transactie volledig te beschrijven.
Transactielogboekarchitectuur
Logvolgnummers
Een logboekrecord heeft een uniek, automatisch oplopend logboekvolgnummer (LSN ), waarmee we dit record in het transactielogboek kunnen vinden. LSN beschrijft de gegevenswijziging en bevat de volgende informatie:
- de bewerking en de betreffende rij
- de oude en nieuwe versies van de gegevens
- de transactie die de wijziging heeft uitgevoerd
LSN bestaat uit drie cijfers:
LSN =
Elke pagina met gegevensbestanden heeft een LSN in de paginakop die de meest recente logrecord identificeert waarvan de wijziging op de pagina wordt weergegeven. Dit is essentieel voor herstel na een crash.
Wanneer het crashherstel wordt uitgevoerd, vergelijkt het de LSN's van logboekrecords voor vastgelegde of niet-vastgelegde transacties met LSN's in gegevensbestandspagina's om te bepalen of er iets opnieuw of ongedaan moet worden gemaakt op die specifieke logboekrecords.
Wanneer u een database aanmaakt, is het een goede gewoonte om de grootte van het transactielogboek op te geven . Als u dit niet doet, maakt SQL Server automatisch het transactielogboek met de standaardgrootte.
De standaardgrootte van het transactielogboek van een nieuwe database is de grootste van 0,5 MB of 25% van de totale grootte van alle gegevensbestanden die in dezelfde CREATE DATABASE-instructie zijn gemaakt.
Je moet heel voorzichtig zijn omdat nieuwe delen van het transactielogboek altijd nul-geïnitialiseerd zijn . Als u de instructie CREATE DATABASE hebt zonder de grootte van het logbestand op te geven, en u maakt bijvoorbeeld een database van 1 TB, dan maakt SQL Server het transactielogboek van 250 GB.
Omdat het logboek op nul moet worden geïnitialiseerd, maakt het geen gebruik van de directe bestandsinitialisatie. Deze functie is toegevoegd in SQL Server 2005 zodat de gegevensbestanden vrijwel onmiddellijk kunnen worden gemaakt of uitgebreid.
We kunnen zien wat er aan de hand is wanneer we DATABASE MAKEN - de nul-initialisatie vindt plaats van ons logboek met behulp van trace flag 3004 die berichten afdrukt over nul-initialisatie en traceervlag 3605 waarmee u die logberichten kunt afdrukken met de traceervlag 3004.
De volgende demo laat zien hoe je het op nul zetten van het logbestand kunt zien gebeuren.
1. Voer het volgende script uit om er zeker van te zijn dat we geen database hebben met de naam 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. Schakel traceervlaggen in om nul-initialisatie te bekijken
DBCC TRACEON (3605, 3004, -1);
GO
3. Flush the error log
EXEC sp_cycle_errorlog;
GO
3. Maak een 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. Lees het foutenlogbestand
EXEC sys.xp_readerrorlog;
GO
Virtuele logbestanden
Het transactielogboek is intern opgesplitst in een reeks brokken die virtuele logbestanden worden genoemd (VLF's ) om het beheer te vereenvoudigen.
Telkens wanneer een transactielogboek wordt gemaakt, geeft het een bepaald aantal VLF's. Nieuw gemaakte VLF's zijn inactief en ongebruikt. Een actieve VLF kan niet opnieuw worden gebruikt totdat deze inactief is gemaakt door het wissen van de logbestanden.
Er is echter één uitzondering:de eerste VLF in een nieuwe database is altijd actief omdat elk transactielogboek ten minste één actieve VLF moet hebben.
Elk logbestand heeft ook een bestandskoppagina wat 8KB . kost aan het begin van het transactielogbestand. Op de koptekstpagina van het bestand worden metagegevens over het bestand opgeslagen, zoals instellingen voor grootte en automatische groei.
Het aantal en de grootte van VLF's in een nieuw gedeelte van het transactielogboek worden bepaald door SQL Server. Het is onmogelijk om het te configureren.
Als de nieuw toegevoegde maat is:
- <1 MB is niet relevant voor discussie
- <64 MB er komen 4 nieuwe VLF's (elk 1/4 van de groei)
- 64 MB tot 1 GB, er komen 8 nieuwe VLF's (elk 1/8 van de groei)
- > 1 GB zijn er 16 nieuwe VLF's (elk 1/16 van de groei)
Dit geldt voor het initieel aangemaakte transactielogboek en voor elke handmatige of automatische groei die optreedt. Als u de formule van het potentiële aantal VLF's en hun potentiële grootte kent, helpt het om het logboek te beheren. Te weinig of te veel VLF's kunnen prestatieproblemen veroorzaken bij transactielogboekbewerkingen.
VLF-volgnummer
Elke VLF heeft een volgnummer om de VLF uniek te identificeren in het transactielogboek. Elke keer dat het logbeheersysteem de volgende VLF activeert, wordt het volgnummer met één verhoogd. De reeks van de volgnummers geeft de huidige actieve set VLF's.
Het begin van het actieve gedeelte van het transactielogboek begint met een VLF met het laagste volgnummer en is nog steeds actief. Inactieve VLF's hebben volgnummers, maar ze maken geen deel uit van het actieve logboekgedeelte.
Het actieve gedeelte van het logboek bevat logboekrecords die om de een of andere reden vereist zijn door SQL Server.
Wanneer u voor het eerst een nieuwe database aanmaakt, beginnen de VLF-volgnummers niet bij 1. Ze beginnen met het hoogste VLF-volgnummer in het transactielogboek van de modeldatabase, plus 1 . Het is onmogelijk om zonder VLF-volgnummers te komen. SQL Server heeft code die ervoor zorgt dat de instantie wordt afgesloten als een VLF-volgnummer ooit nul wordt (als het volgende VLF-volgnummer kleiner is dan het vorige).
VLF- en logblokken
Binnen VLF's zijn er logblokken van verschillende grootte. De minimale grootte van het logblok is 512 bytes en logblokken groeien tot een maximale grootte van 60 KB . De grootte wordt ingesteld wanneer een van de volgende gevallen zich voordoet:
- Een transactie genereert een logrecord om een transactie vast te leggen of af te ronden
- De grootte van het logblok bereikt 60 KB zonder dat een transactie wordt uitgevoerd of afgebroken
Er zijn logrecords in een logblok (gekleurd op het diagram). Logrecords zijn ook variabel van grootte. Het diagram laat zien dat logboekrecords van meerdere gelijktijdige transacties binnen hetzelfde logboekblok kunnen bestaan. De logrecords worden opgeslagen in de volgorde waarin ze zijn geschreven, vergelijkbaar met een gegevenspaginabestand.
Elke VLF bevat een VLF-header met de volgende informatie:
- Of de VLF nu actief is of niet.
- Het logvolgnummer toen de VLF werd gemaakt.
- De huidige pariteitsbits voor alle 512-byte blokken in de VLF.
De pariteitsbits beginnen bij 64 voor de allereerste keer dat VLF wordt gebruikt. Als VLF inactief wordt, maar verder opnieuw wordt geactiveerd, worden de pariteitsbits 128. Deze worden gebruikt tijdens crashherstel.
De details van het transactielogboek onderzoeken – DBCC LOGINFO
De enige manier om naar de transactielogstructuur te kijken, is door de ongedocumenteerde DBCC LOGINFO te gebruiken. opdracht. De syntaxis voor de opdracht is:
DBCC LOGINFO [({'dbname | dbid'})]
Als u dbname niet opgeeft en dbid , het zal u de loginhoud voor de huidige database dumpen.
Het resultaat is één rij voor elke VLF die in het transactielogboek voor die database staat. De geretourneerde velden zijn:
- RecoveryUnitId — toegevoegd in SQL Server 2012 maar momenteel niet gebruikt
- Bestands-ID — transactielogbestand ID binnen een database.
- Bestandsgrootte — VLF-grootte in bytes.
- StartOffset — beginoffset van de VLF in het transactielogbestand, in bytes
- FSeqNee — Het VLF-volgnummer
- Status — Of de VLF actief is of niet (0 =inactief, 2 =actief, 1 – wordt niet gebruikt)
- Pariteit — huidige pariteitsbits (64 of 128, of 0 als de VLF nooit actief is geweest)
- LSN maken — de LSN toen de VLF werd gemaakt (0 =de VLF werd gemaakt toen het transactielogbestand voor het eerst werd gemaakt). Alle andere VLF's die zijn toegevoegd na de eerste aanmaak van het transactielogbestand, hebben CreateLSN die niet nul is.
We kunnen het volgende commando uitvoeren voor de DBTest2014 database, die we eerder hebben gemaakt:
DBCC LOGINFO (N'DBTest2014');
GO
Bekijk het resultaat:
DBCC SQLPERF (LOGSPACE)
De enige manier in Transact-SQL om de hoeveelheid gebruikte log te onderzoeken, is DBCC SQLPERF. De syntaxis voor de opdracht is:
DBCC SQLPERF
(
[ LOGSPACE ]
|
[ "sys.dm_os_latch_stats" , CLEAR ]
|
[ "sys.dm_os_wait_stats" , CLEAR ]
)
[WITH NO_INFOMSGS ]
De opdracht retourneert een resultatenset met één rij per database:
- Databasenaam
- Loggrootte (MB)
- Gebruikte logruimte (%)
- Status:altijd op nul zetten
In mijn omgeving het volgende commando:
DBCC SQLPERF (LOGSPACE);
GO
Geeft het volgende resultaat:
In het volgende artikel gaan we logrecords onderzoeken.