sql >> Database teknologi >  >> RDS >> Sqlserver

SQL Server Transaction Log — Del 2

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


  1. 5 måder at køre et SQL-script fra en fil i SQLite

  2. Hvad er STATISTICS IO i SQL Server?

  3. Hvordan opretter man en database i SQL?

  4. Kan ikke indlæse sqlite-databasen ved første kørsel