Dette er den anden artikel i serien dedikeret til SQL Server-transaktionslog og dens specificiteter. Her skal vi undersøge detaljerne i logposten.
Logposter
Logposter er kernen i lognings- og gendannelsesmekanismerne. En logpost beskriver en enkelt ændring i en database. Således har hver ændring af en database en log-record eller log-records, der hjælper med at beskrive den pågældende ændring. Selvom du ikke behøver at forstå logpostdetaljer, er disse detaljer yderst interessante for at forstå, hvad der foregår med logning og gendannelse.
Logposten har et unikt logsekvensnummer, som vi definerede i den første artikel. Logsekvensnummeret gør det muligt at finde logposten i transaktionsloggen. Derudover har hver datafilside et LSN i sidehovedet, der identificerer den seneste logpost, hvis ændring afspejles på siden. Dette er afgørende for gendannelse af nedbrud.
Logposter for samtidige transaktioner blandes i transaktionsloggen i henhold til, hvornår de fandt sted i tide. Logposter gemmes i logblokke i bufferpuljen, indtil de tømmes til disken.
Der er ingen ikke-loggede operationer i bruger- eller systemdatabaser. Der er dog en undtagelse:i tempdb logges versionslager og arbejdsfiloperationer ikke. Logposter flytter sig aldrig i transaktionsloggen.
Hvad er inde i en logpost?
Oplysninger i en logpost gør det muligt at lave den om (rullet frem) eller fortryde (rullet tilbage). Denne evne til en logpost er afgørende for at tillade transaktioner at blive rullet tilbage og for gendannelsesarbejde. Logposter indeholder mange felter, afhængigt af typen af logpost. Der er nogle felter, der er fælles for alle poster, herunder:
- Logposttypen
- begynd registrering af transaktionslog
- forpligtelse af transaktionslogpost
- tildeling af en side ved at ændre allokeringsbitmap
- indsættelse af en række
- sletning af en række
- ændring af en række
- Konteksten for logposten , hvis nogen.
- Det transaktions-id, logposten er en del af hvis nogen. De fleste logposter er en del af transaktioner.
- Længden af logposten . Logposter har normalt en fast størrelse, og afhængigt af mængden af data, der er i logposten, vil der også være en variabel del.
- LSN for den forrige logpost i samme transaktion . Hvis nogen. LSN'et er i det væsentlige en pegepind til den tidligere transaktionslogpost, der blev genereret af den pågældende transaktion. Denne kæde af de tidligere LSN'er gør det muligt for den pågældende transaktion at blive rullet tilbage, fordi tilbagerulningen sker i omvendt rækkefølge, startende ved den seneste logpost.
- Mængden af reserveret logplads i tilfælde af at logposten skal fortrydes.
Log pladsreservation
Hver logpost, der genereres i den forreste del af en transaktion, skal reservere ledig plads i transaktionsloggen for at tillade, at logposten kan rulles tilbage, uden at transaktionsloggen skal vokse.
Logpladsreservationsmekanismen er meget konservativ og reserverer altid nok plads og normalt mere, bare hvis en uventet situation opstår. For eksempel vil en opdatering eller sletning på en komprimeret tabel reservere mere plads end en lignende opdatering eller sletning på en ikke-komprimeret tabel. Dette sker, fordi tilbagerulningen af opdateringen på den komprimerede tabel muligvis skal klare, at den opdaterede række ikke længere er på en komprimeret side, og derfor skulle skrive kolonner i fuld bredde i logposten i stedet for komprimerede data.
Logposttyper
Der er mange typer logposter, herunder:
- LOP_FORMAT_PAGE Logformat-sideoperationen - er hvor en side er blevet formateret, hvilket betyder, at dens overskrift er blevet oprettet. Logposten vil i det mindste logge sidehovedet og muligvis noget mere indhold på siden, hvis siden er blevet oprettet og udfyldt som en del af en operation som f.eks. en indeksbygning eller ombygning)
- LOP_MODIFY_ROW Denne handling ændrer en lille del af eksisterende data.
- LOP_SET_BITS Denne logpost gælder for allokeringsbitmaps.
- LOP_INSERT_ROWS og LOP_DELETE_ROWS
- LOP_SET_FREE_SPACE Gælder for PFS – allokeringen bitmap, der holder styr på allokeringsstatusser for sider.
Alle logposter, der skal ændre en dataside eller en indeksside i et tabelindeks, omfatter :
- Tildelingsenhedens ID
- Side-id'et og slot-id'et for posten på siden, som i det væsentlige er det nul-baserede post-id for data- eller indeksposten på siden.
- Efter-billedet eller før-billedet og efterbilledet af de ændrede data. Der kan være flere sæt af disse i en enkelt logpost. Efterbilleder tillader gentagelse at ske. Før-billeder gør det muligt at fortryde.
Lås logning
Nogle logposter inkluderer en bitmap over, hvilke låse der blev holdt, da den beskrevne ændring fandt sted. Bitmap'et indeholder:
- Optælling af antallet af låse.
- Hvilken type og tilstand af lås – for eksempel en sidelås i X-tilstand.
- Hvad låsen er slået til
Under nedbrudsgendannelse og databasespejling/tilgængelighedsgruppe-failovers, vil disse låse blive erhvervet for alle logposter, der skal fortrydes. Dette tillader den hurtige gendannelsesfunktion i Enterprise Edition fra SQL Server 2005 og fremefter.
Log registreringer i transaktioner
Alle transaktioner genererer mindst tre logposter, altid i følgende rækkefølge:
- LOP_BEGIN_XACT – inkluderer oplysninger som SPID, transaktionsnavn og starttidspunkt. Alle transaktioner startet af SQL Server har navne til at beskrive operationen (f.eks. AllocFirstPage, DROPOBJ)
- Andre poster for transaktionen.
- LOP_COMMIT_XACT – hvis transaktionen forpligter.
- LOP_ABORT_XACT – hvis transaktionen ruller tilbage.
Disse inkluderer begge sluttidspunktet for transaktionen.
Logposter i en transaktion er sammenkædet baglæns af LSN. Dette betyder, at den næste logpost, der er genereret for en transaktion, har LSN for den forrige logpost, der blev genereret for denne specifikke transaktion. Dette gør det muligt for transaktionen at blive rullet tilbage korrekt. Nogle logposter er overhovedet ikke-transaktionelle, herunder:
- Ændringer af ledig plads i PFS (umuligt at afstemme med andre transaktioner)
- Differentielle bitmapændringer (kun envejsændring)
Undersøgelse af logposter
Der er to måder at undersøge logposter på. Du kan bruge DBCC LOGINFO-funktionen, men det anbefales at bruge funktionen fn_dblog med tabelværdi. Det har ekstremt simpel syntaks:
SELECT * FROM fn_dblog (startLSN, endLSN); GO
Det er ekstremt kraftfuld funktion, fordi den:
- returnerer et tabelresultatsæt, der nemt kan administreres.
- tillader komplekse prædikater at blive brugt.
- scanner al transaktionslog i den aktive del af loggen, fra starten af den ældste ikke-forpligtede transaktion til den seneste logpost. Dette kan tilsidesættes ved hjælp af sporingsflag 2537
StartLSN- og endLSN-felterne sendes normalt som NULL
Her er demoen:
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
Her er det forkortede resultatsæt. Faktisk returnerer fn_dblog en række forskellige poster som Log record Length, Flag Bits, Log Reserve, AllocUnitId, PageID, SlotID, Previous Page LSN og andre.
Ændring af rækkeindhold
Logændringer logges på to måder:som LOP_MODIFY_ROW eller LOP_MODIFY_COLUMNS optage. Uanset hvilken metode der bruges, vil den logge de bytes, der faktisk bliver ændret. For eksempel logger ændring af en INT-værdi fra 1 til 24 kun én byte af ændring, da de andre tre nulbytes ikke ændrede sig. SQL Server vil bruge en LOP_MODIFY_ROW logpost, hvis der er en enkelt del af rækken, der opdateres. En del er defineret som følger:hver kolonne med variabel længde i rækken er en "del", og hele området med fast bredde af rækken er en "del", selvom flere kolonner opdateres, men kun hvis bytes er opdateret er 16 bytes eller mindre fra hinanden i rækken.
LOP_MODIFY_ROW indeholder:
- Før billede
- Efter billede
- Indeks nøglekolonner, hvis det er relevant
- Lås bitmap
LOP_MODIFY_COLUMNS indeholder:
- Før og efter offsets array
- Længde array
- Indeks nøglekolonner, hvis det er relevant
- Lås bitmap
- Før og efter billedpar
Kompensationslogposter
Dette er en speciel slags logposter, der bruges til at hjælpe med en tilbagerulning af transaktioner. Når en transaktion ruller tilbage, skal ændringen beskrevet af hver logpost i transaktionen fortrydes i databasen. Tilbageføring starter med den seneste logpost for transaktionen og følger de tidligere LSN-links indtil LOP_BEGIN_XACT-logposten. For hver logpost:
- Udfør "anti-operationen", der vil ophæve virkningerne af logposten
- Generer en logpost ved at markere den som en KOMPENSATION-logpost, da den kompenserer for logposten i den videregående del af transaktionen.
- KOMPENSATION-logpostens tidligere LSN peger på logposten før den, den kompenserer for. Det medfører i bund og grund, at logposten ikke længere er en del af kæden af logposter for transaktionen.
- Den reserverede logplads til logposten frigives
KOMPENSATION-logposter kan ikke fortrydes, kun gøres om.
Tilbageføring af en transaktion
Her er en grafisk fremstilling af, hvad der foregår, når en transaktion ruller tilbage:
Lad os undersøge følgende kode:
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);
Her kan vi se en speciel logpost med beskrivelsen "KOMPENSATION"
Hvis vi ser på tidligere LSN, kan vi se, at LOP_INSERT_ROWS som vi gjorde, linker tilbage til …0f40:0001 og dette er BEGIN-transaktionen, fordi den forreste del af transaktionen linker tilbage til den tidligere logpost. LOP_DELETE_ROW kompensationslogposten linker ikke tilbage til en post, den kompenserer for - den linker til den (til BEGIN transaktionslogposten).
Så DELEDE har kompenseret for INSERT og fjernet det fra listen over logposter. LOP_ABORT_XACT er signalet om, at transaktionen er afsluttet med tilbagerulningen. Du kan også se det LOP_ABORT_XACT links tilbage til LOP_BEGIN_XACT.
Når vi laver en kompensationslogpost, falder logpladsreservationen [-74]. Så det giver faktisk noget plads tilbage, der var reserveret til den forreste del af transaktionen (LOP_INSERT_ROWS [178]). Som du kan se, er logpladsreservationssystemet meget konservativt - INSERT reserverer mere plads, end DELETE giver tilbage.
Tilbageføringer og differentielle sikkerhedskopier
Hvis en database har en fuld backup, så opdaterer en transaktion 100.000 poster, men transaktionen rulles tilbage, hvorfor sikkerhedskopierer en differentiel backup så meget data? Transaktionens tilbagerulning betyder vel, at intet ændrede sig? Den puslespilsbrik, der mangler her, er, at tilbagerulning af en transaktion ikke udsletter alle ændringer foretaget af transaktionen. Som vi har set, skal tilbagerulningen generere kompensationslogposter, fordi tilbagerulningen skal generere andre ændringer for at kompensere for den fremadrettede del af transaktionen. Sidehovederne på alle berørte sider blev ændret mindst to gange. Én for at opdatere sidens LSN for den fremadrettede del af transaktionen og én gang for at opdatere sidens LSN for tilbagerulningsdelen af transaktionen. I begge tilfælde vil opdateringen medføre, at omfanget markeres som ændret i den differentielle bitmap. Det er ligeglad med, hvad ændringen var, bare at noget i omfanget ændrede sig. Der er ingen måde at udelukke disse omfang fra den differentielle backup.
Oversigt
I denne artikel har vi set på logposterne. Logposter er kernen i lognings- og gendannelsesmekanismerne. Hver ændring i en database har en logpost tilknyttet. Hver logpost beskriver en lille ændring. En stor ændring har flere logposter i en enkelt transaktion. Der er mange forskellige typer logposter, og vi har kigget på få af dem.
Transaktionsloggen er i det væsentlige et stort emne, og et par artikler er ikke tilstrækkelige til at afsløre alle detaljerne. Så hvis du ønsker at få mere detaljeret information, vil jeg foreslå dig at læse følgende bog:SQL Server Transaction Log Management af Tony Davis og Gail Shaw og denne artikel:Administration af transaktionslog.
Læs også:
Dyk ind i SQL Server-transaktionslog — del 1
Dyk ind i SQL Server-transaktionslog — del 2