sql >> Database >  >> RDS >> Sqlserver

SQL Server-transactielogboek - Deel 2

Dit is het tweede artikel in de serie gewijd aan het transactielogboek van SQL Server en de specifieke kenmerken ervan. Hier gaan we de details van het logboek bekijken.

Logrecords

Logrecords vormen de kern van de logging- en herstelmechanismen. Een logboekrecord beschrijft een enkele wijziging in een database. Elke wijziging in een database heeft dus een logrecord of logrecords die helpen om die specifieke wijziging te beschrijven. Hoewel u de details van logboekrecords niet hoeft te begrijpen, om te begrijpen wat er gebeurt met logboekregistratie en herstel, zijn die details buitengewoon interessant.

Het logboekrecord heeft een uniek logboekvolgnummer dat we in het eerste artikel hebben gedefinieerd. Met het logvolgnummer kan het logrecord worden gevonden in het transactielog. Bovendien heeft elke pagina met gegevensbestanden 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.

Logboekrecords voor gelijktijdige transacties worden vermengd in het transactielogboek op basis van wanneer ze op tijd zijn opgetreden. Logrecords worden opgeslagen in logblokken in de bufferpool totdat ze naar schijf worden gewist.

Er zijn geen niet-gelogde bewerkingen in gebruikers- of systeemdatabases. Er is echter een uitzondering:in tempdb worden de bewerkingen voor versieopslag en werkbestanden niet gelogd. Logrecords verplaatsen zich nooit in het transactielogboek.

Wat staat er in een logboekrecord?

Informatie in een logboekrecord maakt het mogelijk om het opnieuw te doen (naar voren geschoven) of ongedaan te maken (teruggedraaid). Dit vermogen van een logboekrecord is cruciaal om transacties terug te draaien en voor herstelwerkzaamheden. Logboekrecords bevatten veel velden, afhankelijk van het type logrecord. Er zijn enkele velden die alle records gemeen hebben, waaronder:

  • Het type logrecord
    • begin transactielogboekrecord
    • transactielogrecord vastleggen
    • een pagina toewijzen door de toewijzingsbitmap te wijzigen
    • een rij invoegen
    • een rij verwijderen
    • een rij aanpassen
  • De context van het logrecord , indien van toepassing.
  • De transactie-ID waar het logrecord deel van uitmaakt indien van toepassing. De meeste logrecords maken deel uit van transacties.
  • De lengte van het logrecord . Logrecords hebben meestal een vaste grootte, en afhankelijk van de hoeveelheid gegevens die in het logrecord zit, zal er ook een variabel gedeelte zijn.
  • De LSN van het vorige logrecord in dezelfde transactie . Indien van toepassing. De LSN is in wezen een verwijzing naar het vorige transactielogboekrecord dat door die specifieke transactie is gegenereerd. Met deze keten van de vorige LSN's kan die specifieke transactie worden teruggedraaid, omdat het terugdraaien in omgekeerde volgorde wordt gedaan, te beginnen bij het meest recente logrecord.
  • De hoeveelheid gereserveerde logruimte in het geval dat de logrecord ongedaan gemaakt moet worden.

Reservering logruimte

Elk logrecord dat in het voorste deel van een transactie wordt gegenereerd, moet vrije ruimte in het transactielogboek reserveren om het logrecord terug te kunnen draaien, zonder dat het transactielogboek hoeft te groeien.

Het reserveringsmechanisme voor logruimte is zeer conservatief, er wordt altijd voldoende ruimte gereserveerd, en meestal meer, voor het geval zich een onverwachte situatie voordoet. Een update of verwijdering op een gecomprimeerde tabel zal bijvoorbeeld meer ruimte reserveren dan een vergelijkbare update of verwijdering op een niet-gecomprimeerde tabel. Dit gebeurt omdat het terugdraaien van de update op de gecomprimeerde tabel mogelijk te maken heeft met het feit dat de bijgewerkte rij niet langer op een gecomprimeerde pagina staat, en dus kolommen over de volledige breedte in het logboekrecord zou moeten schrijven in plaats van gecomprimeerde gegevens.

Typen logrecords

Er zijn veel soorten logboekrecords, waaronder:

  • LOP_FORMAT_PAGE De paginabewerking in logformaat - is waar een pagina is opgemaakt, wat betekent dat de koptekst is gemaakt. Het logboekrecord gaat in ieder geval de paginakop en mogelijk wat meer inhoud van de pagina loggen als de pagina is gemaakt en ingevuld als onderdeel van een bewerking zoals het bouwen of opnieuw opbouwen van een index)
  • LOP_MODIFY_ROW Deze bewerking verandert een klein deel van bestaande gegevens.
  • LOP_SET_BITS Dit logrecord is van toepassing op toewijzingsbitmaps.
  • LOP_INSERT_ROWS en LOP_DELETE_ROWS
  • LOP_SET_FREE_SPACE Is van toepassing op PFS – de toewijzing van de bitmap die de toewijzingsstatussen van pagina's bijhoudt.

Alle logboekrecords die een wijziging gaan aanbrengen in een gegevenspagina of een indexpagina in een tabelindex omvatten :

    • De toewijzingseenheid-ID
    • De pagina-ID en slot-ID van het record op de pagina, wat in wezen de op nul gebaseerde record-ID is van de gegevens- of indexrecord op de pagina.
    • Het na-beeld, of het voor-beeld en na-beeld van de gewijzigde gegevens. Er kunnen meerdere sets hiervan in één logboekrecord zijn. Na-beelden maken het mogelijk om opnieuw te doen. Voor-afbeeldingen maken het mogelijk om ongedaan te maken.

Logboekregistratie vergrendelen

Sommige logrecords bevatten een bitmap van welke vergrendelingen werden vastgehouden toen de beschreven wijziging plaatsvond. De bitmap bevat:

      • Tellen van het aantal sloten.
      • Welk type en wijze van vergrendeling – bijvoorbeeld een paginavergrendeling in X-modus.
      • Waar zit het slot op

Tijdens crashherstel en database-mirroring/beschikbaarheidsgroepfailovers, worden deze vergrendelingen verkregen voor alle logrecords die ongedaan worden gemaakt. Dit maakt de snelle herstelfunctie in Enterprise Edition vanaf SQL Server 2005 mogelijk.

Registraties in transacties loggen

Alle transacties genereren ten minste drie logrecords, altijd in de volgende volgorde:

        • LOP_BEGIN_XACT - bevat informatie zoals de SPID, transactienaam en starttijd. Alle transacties die door SQL Server zijn gestart, hebben namen om de bewerking te beschrijven (bijv. AllocFirstPage, DROPOBJ)
        • Andere records voor de transactie.
        • LOP_COMMIT_XACT – als de transactie wordt vastgelegd.
        • LOP_ABORT_XACT – als de transactie wordt teruggedraaid.

Deze bevatten beide de eindtijd van de transactie.
Logrecords in een transactie worden achterstevoren aan elkaar gekoppeld door LSN. Dit betekent dat het volgende logboekrecord dat voor een transactie wordt gegenereerd, het LSN heeft van het vorige logboekrecord dat voor deze specifieke transactie is gegenereerd. Hierdoor kan de transactie correct worden teruggedraaid. Sommige logrecords zijn helemaal niet-transactioneel, waaronder:

        • Wijzigingen in PFS-vrije ruimte (onmogelijk in overeenstemming te brengen met andere transacties)
        • Differentiële bitmapwijzigingen (alleen eenrichtingswijziging)

Logrecords onderzoeken

Er zijn twee manieren om logboekrecords te onderzoeken. U kunt de functie DBCC LOGINFO gebruiken, maar het wordt aanbevolen om de functie fn_dblog met tabelwaarde te gebruiken. Het heeft een uiterst eenvoudige syntaxis:

SELECT * FROM fn_dblog (startLSN, endLSN);
GO

Het is een extreem krachtige functie omdat het:

        • retourneert een resultatenset in tabelvorm die gemakkelijk kan worden beheerd.
        • maakt het gebruik van complexe predikaten mogelijk.
        • scant alle transactielogboeken in het actieve gedeelte van het logboek, vanaf het begin van de oudste niet-vastgelegde transactie tot het meest recente logboekrecord. Dit kan worden overschreven met traceringsvlag 2537

De startLSN- en endLSN-velden worden meestal doorgegeven als NULL
Hier is de demo:

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

Hier is de verkorte resultatenset. Fn_dblog retourneert feitelijk een verscheidenheid aan verschillende records, zoals de lengte van de logrecord, vlagbits, logreserve, AllocUnitId, PageID, SlotID, LSN voor vorige pagina en andere.

Rij-inhoud wijzigen

Logboekwijzigingen worden op twee manieren vastgelegd:als LOP_MODIFY_ROW of LOP_MODIFY_COLUMNS Vermelding. Welke methode ook wordt gebruikt, het registreert de bytes die daadwerkelijk worden gewijzigd. Als u bijvoorbeeld een INT-waarde van 1 naar 24 wijzigt, wordt slechts één byte aan verandering geregistreerd, aangezien de andere drie nulbytes niet zijn gewijzigd. SQL Server gebruikt een LOP_MODIFY_ROW log-record als er een enkel deel van de rij wordt bijgewerkt. Een gedeelte wordt als volgt gedefinieerd:elke kolom met variabele lengte in de rij is een "gedeelte" en het gehele gebied met vaste breedte van de rij is een "gedeelte", zelfs als meerdere kolommen worden bijgewerkt, maar alleen als de bytes bijgewerkt zijn 16 bytes of minder uit elkaar in de rij.

LOP_MODIFY_ROW bevat:

  • Voor afbeelding
  • Na afbeelding
  • Indexsleutelkolommen indien van toepassing
  • Bitmap vergrendelen

LOP_MODIFY_COLUMNS bevat:

  • Voor en na offsets-array
  • Lengte array
  • Indexsleutelkolommen indien van toepassing
  • Bitmap vergrendelen
  • Voor en na afbeeldingsparen

Compensatielogboekrecords

Dit is een speciaal soort logboekrecords die worden gebruikt om een ​​transactie terug te draaien. Wanneer een transactie wordt teruggedraaid, moet de wijziging die wordt beschreven door elk logboekrecord in de transactie ongedaan worden gemaakt in de database. Rollback begint met het meest recente logboekrecord voor de transactie en volgt de vorige LSN-koppelingen tot het LOP_BEGIN_XACT-logboekrecord. Voor elk logboekrecord:

  • Voer de "anti-operatie" uit die de effecten van het logrecord tenietdoet
  • Genereer een logrecord en markeer het als een COMPENSATIE-logrecord, omdat het de logrecord in het voorste deel van de transactie compenseert.
  • De vorige LSN van het COMPENSATION-logrecord verwijst naar het logrecord van vóór het record waarvoor wordt gecompenseerd. Het zorgt er in wezen voor dat het logrecord niet langer deel uitmaakt van de keten van logrecords voor de transactie.
  • De gereserveerde logruimte voor de logrecord is vrijgegeven

COMPENSATIE log-records kunnen niet ongedaan worden gemaakt, alleen opnieuw worden gedaan.

Een transactie terugdraaien

Hier is een grafische weergave van wat er gebeurt als een transactie wordt teruggedraaid:

Laten we de volgende code eens bekijken:

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);

Hier kunnen we een speciaal logrecord zien met de beschrijving "COMPENSATIE"

Als we naar de vorige LSN kijken, zien we dat LOP_INSERT_ROWS dat we deden, linkt terug naar …0f40:0001 en dit is de BEGIN-transactie omdat het voorwaartse deel van de transactie teruglinkt naar het vorige logrecord. De LOP_DELETE_ROW compensatielogrecord linkt niet terug naar een record waarvoor het compenseert — het linkt ernaar (naar het BEGIN transactielogrecord).

Dus DELEDE heeft INSERT gecompenseerd en verwijderd uit de lijst met logrecords. DeLOP_ABORT_XACT is het signaal dat de transactie wordt beëindigd met het terugdraaien. Je kunt ook zien dat LOP_ABORT_XACT linkt terug naar de LOP_BEGIN_XACT.
Als we een compensatielogbestand maken, daalt de reservering van de logruimte [-74]. Het geeft dus eigenlijk wat ruimte terug die was gereserveerd voor het voorste deel van de transactie (LOP_INSERT_ROWS [178]). Zoals u kunt zien, is het reserveringssysteem voor logruimte erg conservatief — de INSERT reserveert meer ruimte dan de DELETE teruggeeft.

Terugdraaien en differentiële back-ups

Als een database een volledige back-up heeft, dan werkt een transactie 100.000 records bij, maar de transactie wordt teruggedraaid, waarom maakt een differentiële back-up dan zoveel gegevens? Het terugdraaien van de transactie betekent toch dat er niets is veranderd? Het puzzelstukje dat hier ontbreekt, is dat het terugdraaien van een transactie niet alle wijzigingen die door de transactie zijn aangebracht, tenietdoet. Zoals we hebben gezien, moet de rollback compensatielogboekrecords genereren, omdat de rollback andere wijzigingen moet genereren om het voorwaartse deel van de transactie te compenseren. De paginakoppen van alle betrokken pagina's zijn minstens twee keer gewijzigd. Eén om het LSN van de pagina bij te werken voor het voorwaartse deel van de transactie en één keer om het LSN van de pagina bij te werken voor het terugdraaigedeelte van de transactie. In beide gevallen zorgt de update ervoor dat de mate wordt gemarkeerd als gewijzigd in de differentiële bitmap. Het maakt niet uit wat de verandering was, alleen dat er iets in de mate is veranderd. Er is geen manier om deze gebieden uit te sluiten van de differentiële back-up.

Samenvatting

In dit artikel hebben we gekeken naar de logboekrecords. Logrecords vormen de kern van de logging- en herstelmechanismen. Aan elke wijziging in een database is een logboekrecord gekoppeld. Elk logboekrecord beschrijft een kleine wijziging. Een grote wijziging heeft meerdere logboekrecords binnen een enkele transactie. Er zijn veel verschillende soorten logboekrecords en we hebben er maar een paar bekeken.

Het transactielogboek is in wezen een enorm onderwerp en een paar artikelen zijn niet voldoende om alle details te onthullen. Dus als je meer gedetailleerde informatie wilt, raad ik je aan het volgende boek te lezen:SQL Server Transaction Log Management door Tony Davis en Gail Shaw en dit artikel:Beheer van transactielogboeken.

Lees ook:

Duik in het transactielogboek van SQL Server — Deel 1
Duik in het transactielogboek van SQL Server — Deel 2


  1. Eenvoudige recursieve query in Oracle

  2. SELECTEER IN een tabelvariabele in T-SQL

  3. Huidige tijd in UTC gebruiken als standaardwaarde in PostgreSQL

  4. Ormlite of sqlite Welke is goed voor Android-perspectief?