Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Journal des transactions SQL Server — Partie 2

Il s'agit du deuxième article de la série consacrée au journal des transactions SQL Server et à ses spécificités. Ici, nous allons examiner les détails de l'enregistrement du journal.

Enregistrements du journal

Les enregistrements de journaux sont au cœur des mécanismes de journalisation et de récupération. Un enregistrement de journal décrit une seule modification dans une base de données. Ainsi, chaque modification apportée à une base de données a un enregistrement de journal ou des enregistrements de journal qui aident à décrire ce changement particulier. Bien que vous n'ayez pas besoin de comprendre les détails des enregistrements de journal, pour comprendre ce qui se passe avec la journalisation et la récupération, ces détails sont extrêmement intéressants.

L'enregistrement de journal a un numéro de séquence de journal unique que nous avons défini dans le premier article. Le numéro de séquence du journal permet de trouver l'enregistrement du journal dans le journal des transactions. De plus, chaque page de fichier de données a un LSN dans son en-tête de page qui identifie l'enregistrement de journal le plus récent dont la modification est reflétée sur la page. Ceci est essentiel pour la récupération après un crash.

Les enregistrements de journal pour les transactions simultanées sont entremêlés dans le journal des transactions en fonction du moment où ils se sont produits dans le temps. Les enregistrements de journaux sont stockés dans des blocs de journaux dans le pool de mémoire tampon jusqu'à ce qu'ils soient vidés sur le disque.

Il n'y a pas d'opérations non consignées dans les bases de données utilisateur ou système. Cependant, il existe une exception :dans tempdb, les opérations de magasin de versions et de fichiers de travail ne sont pas consignées. Les enregistrements du journal ne se déplacent jamais dans le journal des transactions.

Que contient un enregistrement de journal ?

Les informations contenues dans un enregistrement de journal permettent de le rétablir (roll-forward) ou de l'annuler (roll-back). Cette capacité d'un enregistrement de journal est cruciale pour permettre l'annulation des transactions et pour le travail de récupération. Les enregistrements de journal contiennent de nombreux champs, selon le type d'enregistrement de journal. Certains champs sont communs à tous les enregistrements, notamment :

  • Le type d'enregistrement de journal
    • commencer l'enregistrement du journal des transactions
    • valider l'enregistrement du journal des transactions
    • allouer une page en modifiant le bitmap d'allocation
    • insérer une ligne
    • supprimer une ligne
    • modifier une ligne
  • Le contexte de l'enregistrement de journal , le cas échéant.
  • L'ID de transaction dont fait partie l'enregistrement de journal si seulement. La plupart des enregistrements de journaux font partie des transactions.
  • La longueur de l'enregistrement du journal . Les enregistrements de journal ont généralement une taille fixe, puis, en fonction de la quantité de données contenues dans l'enregistrement de journal, il y aura également une partie variable.
  • Le LSN de l'enregistrement de journal précédent dans la même transaction . Si seulement. Le LSN est essentiellement un pointeur vers l'enregistrement du journal des transactions précédent qui a été généré par cette transaction particulière. Cette chaîne des LSN précédents permet à cette transaction particulière d'être annulée, car l'annulation est effectuée dans l'ordre inverse, en commençant par l'enregistrement de journal le plus récent.
  • La quantité d'espace de journal réservée au cas où l'enregistrement du journal doit être annulé.

Réservation d'espace de journal

Chaque enregistrement de journal généré dans la partie avant d'une transaction doit réserver de l'espace libre dans le journal des transactions pour permettre l'annulation de l'enregistrement du journal, sans que le journal des transactions n'ait à croître.

Le mécanisme de réservation d'espace de journalisation est très conservateur, réservant toujours suffisamment d'espace, et généralement plus, juste au cas où une situation inattendue se produirait. Par exemple, une mise à jour ou une suppression sur une table compressée réservera plus d'espace qu'une mise à jour ou une suppression similaire sur une table non compressée. Cela se produit parce que l'annulation de la mise à jour sur la table compressée peut avoir à faire face à la ligne mise à jour qui n'est plus sur une page compressée, et devrait donc écrire des colonnes pleine largeur dans l'enregistrement du journal au lieu des données compressées.

Types d'enregistrement de journal

Il existe de nombreux types d'enregistrements de journaux, notamment :

  • LOP_FORMAT_PAGE L'opération de formatage de page de journal - est l'endroit où une page a été formatée, ce qui signifie que son en-tête a été créé. L'enregistrement du journal va enregistrer au moins l'en-tête de la page et potentiellement un peu plus de contenu de la page si la page a été créée et remplie dans le cadre d'une opération telle qu'une construction ou une reconstruction d'index)
  • LOP_MODIFY_ROW Cette opération modifie une petite partie d'une donnée existante.
  • LOP_SET_BITS Cet enregistrement de journal s'applique aux bitmaps d'allocation.
  • LOP_INSERT_ROWS et LOP_DELETE_ROWS
  • LOP_SET_FREE_SPACE S'applique à PFS - l'allocation du bitmap qui assure le suivi des statuts d'allocation des pages.

Tous les enregistrements de journal qui vont apporter une modification à une page de données ou à une page d'index dans un index tabulaire incluent :

    • L'ID de l'unité d'allocation
    • L'ID de page et l'ID d'emplacement de l'enregistrement sur la page, qui est essentiellement l'ID d'enregistrement de base zéro de l'enregistrement de données ou d'index sur la page.
    • L'image après, ou l'image avant et l'image après des données modifiées. Il peut y en avoir plusieurs ensembles dans un seul enregistrement de journal. Les images rémanentes permettent de refaire. Les images avant permettent de se défaire.

Verrouiller la journalisation

Certains enregistrements de journal incluent un bitmap indiquant quels verrous étaient détenus lorsque la modification décrite a eu lieu. Le bitmap contient :

      • Compte du nombre de verrous.
      • Quel type et mode de verrouillage ? Par exemple, un verrouillage de page en mode X.
      • Sur quoi porte le verrou

Lors de la reprise sur incident et de la mise en miroir de bases de données/des basculements de groupe de disponibilité, ces verrous seront acquis pour tous les enregistrements de journal qui vont être annulés. Cela permet la fonctionnalité de récupération rapide dans Enterprise Edition à partir de SQL Server 2005.

Journal des enregistrements dans les transactions

Toutes les transactions génèrent au moins trois enregistrements de journal, toujours dans l'ordre suivant :

        • LOP_BEGIN_XACT – inclut des informations telles que le SPID, le nom de la transaction et l'heure de début. Toutes les transactions démarrées par SQL Server ont des noms pour décrire l'opération (par exemple, AllocFirstPage, DROPOBJ)
        • Autres enregistrements pour la transaction.
        • LOP_COMMIT_XACT – si la transaction est validée.
        • LOP_ABORT_XACT – si la transaction est annulée.

Ces deux éléments incluent l'heure de fin de la transaction.
Les enregistrements de journal d'une transaction sont reliés entre eux en amont par LSN. Cela signifie que l'enregistrement de journal suivant qui est généré pour une transaction a le LSN de l'enregistrement de journal précédent qui a été généré pour cette transaction particulière. Cela permet d'annuler correctement la transaction.Certains enregistrements de journal ne sont pas du tout transactionnels, notamment :

        • Modifications d'espace libre PFS (impossible de concilier avec d'autres transactions)
        • Modifications différentielles du bitmap (changement unidirectionnel uniquement)

Examiner les enregistrements du journal

Il existe deux façons d'examiner les enregistrements de journal. Vous pouvez utiliser la fonction DBCC LOGINFO, mais il est recommandé d'utiliser la fonction table fn_dblog. Sa syntaxe est extrêmement simple :

SELECT * FROM fn_dblog (startLSN, endLSN);
GO

C'est une fonction extrêmement puissante car elle :

        • renvoie un ensemble de résultats sous forme de tableau facilement gérable.
        • permet d'utiliser des prédicats complexes.
        • analyse tous les journaux de transactions dans la partie active du journal, du début de la transaction non validée la plus ancienne jusqu'à l'enregistrement de journal le plus récent. Cela peut être remplacé à l'aide de l'indicateur de trace 2537

Les champs startLSN et endLSN sont généralement passés comme NULL
Voici la démo :

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

Voici le jeu de résultats raccourci. En fait, fn_dblog renvoie une variété d'enregistrements différents tels que la longueur de l'enregistrement du journal, les bits d'indicateur, la réserve de journal, AllocUnitId, PageID, SlotID, LSN de la page précédente et autres.

Modifier le contenu des lignes

Les modifications de journal sont consignées de deux manières :en tant que LOP_MODIFY_ROW ou LOP_MODIFY_COLUMNS record. Quelle que soit la méthode utilisée, il enregistrera les octets qui sont réellement modifiés. Par exemple, changer une valeur INT de 1 à 24 n'enregistre qu'un octet de changement car les trois autres octets à zéro n'ont pas changé. SQL Server utilisera un LOP_MODIFY_ROW enregistrement de journal si une seule partie de la ligne est mise à jour. Une portion est définie comme suit :chaque colonne de longueur variable dans la ligne est une « portion » et toute la zone à largeur fixe de la ligne est une « portion », même si plusieurs colonnes sont mises à jour, mais uniquement si les octets sont mis à jour sont espacés de 16 octets ou moins dans la ligne.

LOP_MODIFY_ROW contient :

  • Image avant
  • Après l'image
  • Colonnes de clé d'index, le cas échéant
  • Verrouiller le bitmap

LOP_MODIFY_COLUMNS contient :

  • Tableau des décalages avant et après
  • Tableau de longueur
  • Colonnes de clé d'index, le cas échéant
  • Verrouiller le bitmap
  • Avant et après les paires d'images

Enregistrements du journal des rémunérations

Il s'agit d'un type spécial d'enregistrements de journal qui sont utilisés pour faciliter une annulation de transaction. Lorsqu'une transaction est annulée, la modification décrite par chaque enregistrement de journal dans la transaction doit être annulée dans la base de données. La restauration commence par l'enregistrement de journal le plus récent pour la transaction et suit les liens LSN précédents jusqu'à l'enregistrement de journal LOP_BEGIN_XACT. Pour chaque enregistrement de journal :

  • Effectuez l'« anti-opération » qui annulera les effets de l'enregistrement du journal
  • Générez un enregistrement de journal, en le marquant comme un enregistrement de journal COMPENSATION, car il compense l'enregistrement de journal dans la partie avant de la transaction.
  • Le LSN précédent de l'enregistrement du journal COMPENSATION pointe vers l'enregistrement du journal précédant celui qu'il compense. Cela fait essentiellement que l'enregistrement du journal ne fait plus partie de la chaîne d'enregistrements du journal pour la transaction.
  • L'espace de journal réservé pour l'enregistrement de journal est libéré

Les enregistrements du journal COMPENSATION ne peuvent pas être annulés, seulement rétablis.

Annuler une transaction

Voici une représentation graphique de ce qui se passe lorsqu'une transaction est annulée :

Examinons le code suivant :

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

Ici, nous pouvons voir un enregistrement de journal spécial avec la description "COMPENSATION"

Si nous regardons le LSN précédent, nous pouvons voir que LOP_INSERT_ROWS que nous avons fait, renvoie à …0f40:0001 et il s'agit de la transaction BEGIN car la partie avant de la transaction renvoie à l'enregistrement de journal précédent. Le LOP_DELETE_ROW l'enregistrement du journal de compensation n'est pas lié à un enregistrement pour lequel il compense — il est lié à celui-ci (à l'enregistrement du journal des transactions BEGIN).

Ainsi, DELDE a compensé INSERT et l'a supprimé de la liste des enregistrements de journal. LeLOP_ABORT_XACT est le signal que la transaction est terminée avec la restauration. En outre, vous pouvez voir que LOP_ABORT_XACT renvoie au LOP_BEGIN_XACT.
Lorsque nous effectuons un enregistrement de journal de compensation, la réservation d'espace de journal descend [-74]. Il redonne donc en fait de l'espace qui était réservé pour la partie avant de la transaction (LOP_INSERT_ROWS [178]). Comme vous pouvez le constater, le système de réservation d'espace de journalisation est très conservateur :INSERT réserve plus d'espace que DELETE n'en rend.

Rollbacks et sauvegardes différentielles

Si une base de données fait l'objet d'une sauvegarde complète, qu'une transaction met à jour 100 000 enregistrements mais que la transaction est annulée, pourquoi une sauvegarde différentielle tant de données ? L'annulation de la transaction signifie-t-elle que rien n'a changé ? La pièce du puzzle qui manque ici est que l'annulation d'une transaction n'efface pas toutes les modifications apportées par la transaction. Comme nous l'avons vu, la restauration doit générer des enregistrements de journal de compensation, car la restauration doit générer d'autres modifications pour compenser la partie avant de la transaction. Les en-têtes de toutes les pages concernées ont été modifiés au moins deux fois. Une pour mettre à jour le LSN de la page pour la partie de transfert de la transaction et une fois pour mettre à jour le LSN de la page pour la partie de restauration de la transaction. Dans les deux cas, la mise à jour entraînera le marquage de l'étendue comme modifiée dans le bitmap différentiel. Il ne se soucie pas de savoir quel était le changement, juste que quelque chose dans l'étendue a changé. Il n'y a aucun moyen d'exclure ces étendues de la sauvegarde différentielle.

Résumé

Dans cet article, nous avons examiné les enregistrements du journal. Les enregistrements de journaux sont au cœur des mécanismes de journalisation et de récupération. Chaque modification dans une base de données est associée à un enregistrement de journal. Chaque enregistrement de journal décrit un petit changement. Un changement important a plusieurs enregistrements de journal dans une seule transaction. Il existe de nombreux types d'enregistrements de journaux différents et nous en avons examiné quelques-uns.

Le journal des transactions est un sujet essentiellement énorme et quelques articles ne suffisent pas pour dévoiler tous les détails. Donc, si vous souhaitez obtenir des informations plus détaillées, je vous suggère de lire le livre suivant :SQL Server Transaction Log Management par Tony Davis et Gail Shaw et cet article :Gestion des journaux de transactions.

Lire aussi :

Plongez dans le journal des transactions SQL Server – Partie 1
Plongez dans le journal des transactions SQL Server – Partie 2