Detta är den andra artikeln i serien tillägnad SQL Server transaktionslogg och dess särdrag. Här ska vi undersöka loggpostens detaljer.
Loggposter
Loggposter är kärnan i loggnings- och återställningsmekanismerna. En loggpost beskriver en enda ändring i en databas. Således har varje ändring i en databas en loggpost eller loggposter som hjälper till att beskriva just den förändringen. Även om du inte behöver förstå logguppgifterna, för att förstå vad som händer med loggning och återställning, är dessa detaljer extremt intressanta.
Loggposten har ett unikt loggsekvensnummer som vi definierade i den första artikeln. Loggsekvensnumret gör att loggposten kan hittas i transaktionsloggen. Dessutom har varje datafilsida ett LSN i sidhuvudet som identifierar den senaste loggposten vars ändring återspeglas på sidan. Detta är avgörande för återställning av kraschar.
Loggposter för samtidiga transaktioner blandas i transaktionsloggen efter när de inträffade i tid. Loggposter lagras i loggblock i buffertpoolen tills de spolas till disken.
Det finns inga icke-loggade operationer i användar- eller systemdatabaser. Det finns dock ett undantag:i tempdb loggas versionslagring och arbetsfiloperationer inte. Loggposter flyttas aldrig i transaktionsloggen.
Vad är inuti en loggpost?
Information i en loggpost gör att den kan göras om (rullas framåt) eller ångras (rullas tillbaka). Denna förmåga hos en loggpost är avgörande för att transaktioner ska kunna återställas och för återställningsarbete. Loggposter innehåller många fält, beroende på typen av loggpost. Det finns några fält som är gemensamma för alla poster, inklusive:
- Loggposttypen
- börja transaktionsloggpost
- begär transaktionsloggpost
- tilldela en sida genom att ändra tilldelningsbitmappen
- infoga en rad
- ta bort en rad
- ändra en rad
- Kontexten för loggposten , om någon.
- Transaktions-ID:t som loggposten är en del av om någon. De flesta loggposter är en del av transaktioner.
- Längden på loggposten . Loggposter har vanligtvis en fast storlek, och beroende på mängden data som finns i loggposten kommer det också att finnas en variabel del.
- LSN för den tidigare loggposten i samma transaktion . Om någon. LSN är i huvudsak en pekare till den tidigare transaktionsloggposten som genererades av den specifika transaktionen. Denna kedja av de tidigare LSN:erna tillåter att just den transaktionen återställs, eftersom återställningen görs i omvänd ordning, med början vid den senaste loggposten.
- Mängden reserverat loggutrymme om loggposten måste ångras.
Logg Space Reservation
Varje loggpost som genereras i den framåtriktade delen av en transaktion måste reservera ledigt utrymme i transaktionsloggen så att loggposten kan rullas tillbaka, utan att transaktionsloggen behöver växa.
Reserveringsmekanismen för loggutrymmen är mycket konservativ, reserverar alltid tillräckligt med utrymme, och vanligtvis mer, bara om en oväntad situation skulle inträffa. Till exempel kommer en uppdatering eller borttagning av en komprimerad tabell att reservera mer utrymme än en liknande uppdatering eller radering på en icke-komprimerad tabell. Detta beror på att återställningen av uppdateringen på den komprimerade tabellen kan behöva klara av att den uppdaterade raden inte längre finns på en komprimerad sida, och därför skulle behöva skriva fullbreddskolumner i loggposten istället för komprimerad data.
Loggposttyper
Det finns många typer av loggposter, inklusive:
- LOP_FORMAT_PAGE Sidoperationen för loggformat - är där en sida har formaterats, vilket betyder att dess sidhuvud har skapats. Loggposten kommer att logga åtminstone sidhuvudet och eventuellt mer innehåll på sidan om sidan har skapats och fyllts i som en del av en operation som indexbygge eller ombyggnad)
- LOP_MODIFY_ROW Denna operation ändrar en liten del av befintlig data.
- LOP_SET_BITS Denna loggpost gäller för tilldelningsbitmappar.
- LOP_INSERT_ROWS och LOP_DELETE_ROWS
- LOP_SET_FREE_SPACE Gäller PFS – allokeringen bitmappen som håller reda på allokeringsstatus för sidor.
Alla loggposter som kommer att göra en ändring av en datasida eller en indexsida i ett tabellindex inkluderar :
- Tilldelningsenhets-ID
- Sid-ID och plats-ID för posten på sidan, vilket i huvudsak är det nollbaserade post-ID:t för data- eller indexposten på sidan.
- Efterbilden, eller förebilden och efterbilden av de ändrade data. Det kan finnas flera uppsättningar av dessa i en enda loggpost. Efterbilder låter göra om. Före-bilder tillåter ångring.
Lås loggning
Vissa loggposter inkluderar en bitmapp över vilka lås som hölls när den beskrivna ändringen ägde rum. Bitmappen innehåller:
- Antalet lås.
- Vilken typ och läge för lås – till exempel ett sidlås i X-läge.
- Vad låset är på
Under kraschåterställning och databasspegling/tillgänglighetsgruppfel, kommer dessa lås att förvärvas för alla loggposter som kommer att ångras. Detta möjliggör snabb återställningsfunktion i Enterprise Edition från SQL Server 2005 och framåt.
Logga poster i transaktioner
Alla transaktioner genererar minst tre loggposter, alltid i följande ordning:
- LOP_BEGIN_XACT – innehåller information som SPID, transaktionsnamn och starttid. Alla transaktioner som startas av SQL Server har namn som beskriver operationen (t.ex. AllocFirstPage, DROPOBJ)
- Andra poster för transaktionen.
- LOP_COMMIT_XACT – om transaktionen binder.
- LOP_ABORT_XACT – om transaktionen rullar tillbaka.
Dessa inkluderar båda sluttiden för transaktionen.
Loggposter i en transaktion länkas ihop bakåt av LSN. Detta betyder att nästa loggpost som genereras för en transaktion har LSN för den föregående loggposten som genererades för just denna transaktion. Detta gör att transaktionen kan återställas korrekt. Vissa loggposter är icke-transaktionella alls, inklusive:
- PFS-ändringar av ledigt utrymme (omöjligt att stämma av med andra transaktioner)
- Differentiella bitmappsändringar (endast envägsändring)
Undersöka loggposter
Det finns två sätt att granska loggposter. Du kan använda DBCC LOGINFO-funktionen, men det rekommenderas att använda funktionen fn_dblog med tabellvärde. Den har extremt enkel syntax:
SELECT * FROM fn_dblog (startLSN, endLSN); GO
Det är extremt kraftfull funktion eftersom den:
- returerar en resultatuppsättning i tabellform som enkelt kan hanteras.
- gör att komplexa predikat kan användas.
- söker igenom alla transaktionsloggar i den aktiva delen av loggen, från början av den äldsta oengagerade transaktionen till den senaste loggposten. Detta kan åsidosättas med spårningsflagga 2537
Fälten startLSN och endLSN skickas vanligtvis som NULL
Här är demon:
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
Här är den förkortade resultatuppsättningen. Faktiskt returnerar fn_dblog en mängd olika poster som loggpostlängd, flaggbitar, loggreservering, AllocUnitId, PageID, SlotID, föregående sida LSN och andra.
Ändra radinnehåll
Loggändringar loggas på två sätt:som LOP_MODIFY_ROW eller LOP_MODIFY_COLUMNS spela in. Oavsett vilken metod som används kommer den att logga de byte som faktiskt ändras. Om du till exempel ändrar ett INT-värde från 1 till 24 loggas bara en byte av förändring eftersom de andra tre nollbytena inte ändrades. SQL Server kommer att använda en LOP_MODIFY_ROW loggpost om det finns en enda del av raden som uppdateras. En del definieras enligt följande:varje kolumn med variabel längd i raden är en "del" och hela området med fast bredd på raden är en "del", även om flera kolumner uppdateras, men bara om byten är uppdaterade är 16 byte eller mindre från varandra i raden.
LOP_MODIFY_ROW innehåller:
- Före-bild
- Efter bild
- Indexera nyckelkolumner om tillämpligt
- Lås bitmapp
LOP_MODIFY_COLUMNS innehåller:
- Före och efter offset array
- Längd array
- Indexera nyckelkolumner om tillämpligt
- Lås bitmapp
- Före och efter bildpar
Kompensationsloggposter
Detta är en speciell typ av loggposter som används för att hjälpa en återställning av transaktioner. När en transaktion rullar tillbaka måste ändringen som beskrivs av varje loggpost i transaktionen ångras i databasen. Återställning börjar med den senaste loggposten för transaktionen och följer de tidigare LSN-länkarna tills LOP_BEGIN_XACT-loggposten. För varje loggpost:
- Utför "anti-operationen" som kommer att förneka effekterna av loggposten
- Skapa en loggpost och markera den som en KOMPENSATION-loggpost, eftersom den kompenserar för loggposten i den vidarebefordrade delen av transaktionen.
- KOMPENSATION-loggpostens tidigare LSN pekar på loggposten före den den kompenserar för. Det gör att loggposten inte längre ingår i kedjan av loggposter för transaktionen.
- Det reserverade loggutrymmet för loggposten frigörs
KOMPENSATIONSloggposter kan inte ångras, bara göras om.
Återställa en transaktion
Här är en grafisk representation av vad som händer när en transaktion rullar tillbaka:
Låt oss undersöka följande kod:
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);
Här kan vi se en speciell loggpost med beskrivningen "KOMPENSATION"
Om vi tittar på tidigare LSN kan vi se att LOP_INSERT_ROWS som vi gjorde, länkar tillbaka till …0f40:0001 och detta är BEGIN-transaktionen eftersom den framåtriktade delen av transaktionen länkar tillbaka till den tidigare loggposten. LOP_DELETE_ROW kompensationsloggposten länkar inte tillbaka till en post den kompenserar för – den länkar till den (till BEGIN transaktionsloggposten).
Så DELEDE har kompenserat för INSERT och tagit bort det från listan över loggposter. LOP_ABORT_XACT är signalen att transaktionen avslutas med återställningen. Du kan också se att LOP_ABORT_XACT länkar tillbaka till LOP_BEGIN_XACT.
När vi gör en kompensationsloggpost sjunker loggutrymmesreservationen [-74]. Så det ger faktiskt tillbaka lite utrymme som var reserverat för den framåtriktade delen av transaktionen (LOP_INSERT_ROWS [178]). Som du kan se är bokningssystemet för loggutrymme mycket konservativt — INSERT reserverar mer utrymme än vad DELETE ger tillbaka.
Återkallningar och differentiella säkerhetskopior
Om en databas har en fullständig säkerhetskopia, då uppdaterar en transaktion 100 000 poster men transaktionen rullas tillbaka, varför gör en differentiell säkerhetskopiering så mycket data? Visst betyder återställningen av transaktionen att ingenting har förändrats? Pusselbiten som saknas här är att en återställning av en transaktion inte raderar alla ändringar som görs av transaktionen. Som vi har sett måste återställningen generera kompensationsloggposter, eftersom återställningen måste generera andra ändringar för att kompensera för den framåtriktade delen av transaktionen. Sidhuvudena på alla berörda sidor ändrades minst två gånger. En för att uppdatera sidans LSN för den framåtriktade delen av transaktionen och en gång för att uppdatera sidans LSN för återställningsdelen av transaktionen. I båda fallen kommer uppdateringen att göra att omfattningen markeras som ändrad i den differentiella bitmappen. Det bryr sig inte om vad förändringen var, bara att något i omfattningen förändrades. Det finns inget sätt att utesluta dessa omfattningar från den differentiella säkerhetskopieringen.
Sammanfattning
I den här artikeln har vi tittat på loggposterna. Loggposter är kärnan i loggnings- och återställningsmekanismerna. Varje ändring i en databas har en loggpost kopplad till sig. Varje loggpost beskriver en liten förändring. En stor förändring har flera loggposter i en enda transaktion. Det finns många olika typer av loggposter och vi har tittat på några av dem.
Transaktionsloggen är ett i grunden stort ämne och ett par artiklar räcker inte för att avslöja alla detaljer. Så om du vill få mer detaljerad information skulle jag föreslå att du läser följande bok:SQL Server Transaction Log Management av Tony Davis och Gail Shaw och den här artikeln:Hantering av transaktionsloggar.
Läs även:
Dyk in i SQL Server Transaction Log — Del 1
Dive Into SQL Server Transaction Log — Del 2