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

Journal des transactions SQL Server — Partie 1

Chaque base de données SQL Server contient un ou plusieurs fichiers journaux de transactions en plus des fichiers de données. Les fichiers journaux enregistrent toutes les transactions et les modifications de la base de données effectuées par chacun d'eux.

Cet article se concentre sur le journal des transactions et sur la façon dont SQL Server enregistre les modifications de données pour utiliser les données pour la récupération après incident de la base de données.

Introduction au fichier journal des transactions SQL Server

Comme on s'en souvient, chaque transaction est « tout ou rien ». Si une partie de la transaction échoue, la totalité de la transaction échoue et l'état de la base de données reste inchangé.

SQL Server stocke un enregistrement de chaque transaction effectuée sur la base de données dans le fichier journal. Si un sinistre entraîne l'arrêt de SQL Server, il utilise un journal des transactions pour restaurer la base de données dans un état cohérent avec l'intégrité des données.

Après le redémarrage, SQL Server démarre le processus de récupération après incident. Il lit le fichier journal des transactions pour s'assurer que toutes les données valides sont stockées dans les fichiers de données et que les transactions non validées sont annulées.

En fonctionnement normal, SQL Server utilise également le journal des transactions. Les informations contenues dans le fichier sont nécessaires pour identifier ce que SQL Server doit faire lorsqu'une transaction est annulée en raison d'une erreur ou d'une instruction ROLLBACK spécifiée par l'utilisateur.

Comment SQL Server utilise le journal des transactions

Le journal des transactions est un fichier physique avec l'extension LDF . SQL Server le crée automatiquement pour toute nouvelle base de données avec le fichier de données principal (.MDF ) qui stocke les objets de la base de données et les données elles-mêmes.

Chaque fois que le code T-SQL modifie un objet de base de données ou les données qu'il contient, les détails de la modification sont enregistrés sous la forme d'un enregistrement de journal dans le fichier journal des transactions.

L'enregistrement du journal contient les informations d'une modification spécifique apportée à la base de données (par exemple, insérer une seule ligne). Par conséquent, nous aurons une série d'enregistrements de journal pour décrire pleinement les effets d'une seule transaction.

Architecture du journal des transactions

Numéros de séquence de journal

Un enregistrement de journal a un numéro de séquence de journal unique qui s'incrémente automatiquement (LSN ), qui nous permet de retrouver cet enregistrement dans le journal des transactions. LSN décrit le changement de données et contient les informations suivantes :

  • l'opération et la ligne concernée
  • l'ancienne et la nouvelle version des données
  • la transaction qui a effectué la modification

LSN est composé de trois chiffres :

LSN = : :

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.

Lorsque la récupération sur incident s'exécute, elle compare les LSN des enregistrements de journal pour les transactions validées ou non avec les LSN des pages de fichiers de données pour déterminer s'il y a une opération de rétablissement ou d'annulation à effectuer sur ces enregistrements de journal particuliers.

Lorsque vous créez une base de données, une bonne pratique consiste à spécifier la taille du journal des transactions . Si vous ne le faites pas, SQL Server créera automatiquement le journal des transactions avec la taille par défaut.

La taille par défaut du journal des transactions d'une nouvelle base de données est le plus grand de 0,5 Mo ou 25 % de la taille totale de tous les fichiers de données créés dans la même instruction CREATE DATABASE.

Vous devez être très prudent car les nouvelles parties du journal des transactions sont toujours initialisées à zéro . Si vous avez l'instruction CREATE DATABASE sans spécifier la taille du fichier journal et que vous créez, par exemple, une base de données de 1 To, SQL Server créera le journal des transactions de 250 Go.

Comme le journal doit être initialisé à zéro, il n'utilise pas l'initialisation instantanée du fichier. Cette fonctionnalité a été ajoutée dans SQL Server 2005 pour permettre la création ou la croissance des fichiers de données presque instantanément.

Nous pouvons voir ce qui se passe lorsque nous CREATE DATABASE - l'initialisation zéro se produit de notre journal en utilisant trace flag 3004 qui imprime des messages sur l'initialisation à zéro et l'indicateur de trace 3605 qui permet d'imprimer ces messages de journal par l'indicateur de trace 3004.

La démonstration suivante montre comment vous pouvez voir la mise à zéro du fichier journal se produire.

1. Exécutez le script suivant pour vous assurer que nous n'avons pas de base de données appelée DBTest2014

USE master;
GO
 
IF DATABASEPROPERTY(N'DBTest2014', N'Version')>0
  BEGIN
    ALTER DATABASE DBTest2014 SET SINGLE_USER
      WITH ROLLBACK IMMEDIATE;
    DROP DATABASE DBTest2014;
  END
GO

2. Activer les indicateurs de trace pour surveiller l'initialisation à zéro

DBCC TRACEON (3605, 3004, -1);
GO
3. Flush the error log
EXEC sp_cycle_errorlog;
GO

3. Créez une base de données

CREATE DATABASE DBTest2014 ON PRIMARY (
  NAME = N'DBTest2014',
  FILENAME = N'D:\DBTest2014_data.mdf')
LOG ON (
  NAME= N'DBTest2014_log',
  FILENAME= N'D:\DBTest2014_log.ldf',
  SIZE = 10MB,
  FILEGROWTH = 10 MB);
GO

4. Lisez le fichier journal des erreurs

EXEC sys.xp_readerrorlog;
GO

Fichiers journaux virtuels

Le journal des transactions est divisé en interne en une série de blocs appelés fichiers journaux virtuels (VLF ) pour simplifier la gestion.

Chaque fois qu'un journal des transactions est créé, il donne un certain nombre de VLF. Les VLF nouvellement créés sont inactifs et inutilisés. Un VLF actif ne peut pas être réutilisé tant qu'il n'est pas rendu inactif par l'effacement du journal.

Cependant, il y a une exception - le premier VLF dans une nouvelle base de données est toujours actif car tout journal de transactions doit avoir au moins un VLF actif.

Chaque fichier journal a également une page d'en-tête de fichier qui prend 8 Ko au début du fichier journal des transactions. La page d'en-tête du fichier stocke des métadonnées sur le fichier, telles que la taille et les paramètres de croissance automatique.

Le nombre et la taille des VLF dans une nouvelle partie du journal des transactions sont déterminés par SQL Server. Il est impossible de le configurer.

Si la taille nouvellement ajoutée est :

  • <1 Mo n'est pas pertinent pour la discussion
  • <64 Mo, il y aura 4 nouveaux VLF (chacun 1/4 de la taille de croissance)
  • De 64 Mo à 1 Go, il y aura 8 nouveaux VLF (chacun représentant 1/8 de la taille de croissance)
  • > 1 Go, il y aura 16 nouveaux VLF (chacun 1/16 de la taille de croissance)

Cela s'applique au journal des transactions initialement créé et à chaque croissance manuelle ou automatique qui se produit. Lorsque vous connaissez la formule du nombre potentiel de VLF et leur taille potentielle, cela aide à gérer le journal. Trop peu ou trop de VLF peuvent entraîner des problèmes de performances avec les opérations du journal des transactions.

Numéro de séquence VLF

Chaque VLF a un numéro de séquence pour identifier de manière unique le VLF dans le journal des transactions. Le numéro de séquence augmente d'une unité à chaque fois que le système de gestion des journaux active la VLF suivante. La chaîne des numéros de séquence donne l'ensemble de VLF actuellement actif.

Le début de la partie active du journal des transactions commence par un VLF qui a le numéro de séquence le plus bas et qui est toujours actif. Les VLF inactifs ont des numéros de séquence, mais ils ne font pas partie de la partie active du journal.

La partie active du journal contient des enregistrements de journal requis pour une raison quelconque par SQL Server.

Lorsque vous créez une nouvelle base de données pour la première fois, les numéros de séquence VLF ne commencent pas à 1. Ils commencent par le numéro de séquence VLF le plus élevé dans le journal des transactions de la base de données modèle, plus 1 . Il est impossible de manquer de numéros de séquence VLF. SQL Server a un code qui forcera l'instance à s'arrêter si un numéro de séquence VLF revient à zéro (si le numéro de séquence VLF suivant est inférieur au précédent).

VLF et blocs de journaux

Dans les VLF, il existe des blocs de journal de taille variable. La taille minimale du bloc de journal est de 512 les octets et les blocs de journal atteignent une taille maximale de 60 Ko . La taille est définie lorsque l'un des cas suivants se produit :

  • Une transaction génère un enregistrement de journal pour valider ou terminer l'abandon d'une transaction
  • La taille du bloc de journal atteint 60 Ko sans qu'une transaction ne soit validée ou abandonnée

Il y a des enregistrements de journal dans un bloc de journal (coloré sur le diagramme). Les enregistrements de journal sont également de taille variable. Le diagramme montre que les enregistrements de journal de plusieurs transactions simultanées peuvent exister dans le même bloc de journal. Les enregistrements de journal sont stockés dans l'ordre écrit de la même manière qu'un fichier de page de données.

Chaque VLF contient un en-tête VLF avec les informations suivantes :

  • Si le VLF est actif ou non.
  • Le numéro de séquence du journal lors de la création du VLF.
  • Les bits de parité actuels pour tous les blocs de 512 octets dans le VLF.

Les bits de parité commencent à 64 pour la toute première utilisation VLF. Si VLF devient inactif, mais réactivé, les bits de parité deviendront 128. Ceux-ci sont utilisés lors de la récupération après un crash.

Examiner les détails du journal des transactions – DBCC LOGINFO

La seule façon de regarder la structure du journal des transactions est d'utiliser le DBCC LOGINFO non documenté commande. La syntaxe de la commande est :

DBCC LOGINFO [({'dbname | dbid'})]

Si vous ne spécifiez pas dbname et dbid , il vous videra le contenu du journal pour la base de données actuelle.

Le résultat est une ligne pour chaque VLF qui se trouve dans le journal des transactions de cette base de données. Les champs renvoyés sont :

  • Identifiant d'unité de récupération — ajouté dans SQL Server 2012 mais actuellement inutilisé
  • ID de fichier — ID du fichier journal des transactions dans une base de données.
  • Taille du fichier — Taille VLF en octets.
  • StartOffset — décalage de départ du VLF dans le fichier journal des transactions, en octets
  • FSeqNo — Le numéro de séquence VLF
  • Statut — Si le VLF est actif ou non (0 =inactif, 2 =actif, 1 - n'est pas utilisé)
  • Parité — bits de parité actuels (64 ou 128, ou 0 si le VLF n'a jamais été actif)
  • Créer un LSN — le LSN lors de la création du VLF (0 =le VLF a été créé lors de la création initiale du fichier journal des transactions). Tous les autres VLF ajoutés après la création initiale du fichier journal des transactions auront CreateLSN différent de zéro.

Nous pouvons exécuter la commande suivante pour le DBTest2014 base de données, que nous avons créée précédemment :

DBCC LOGINFO (N'DBTest2014');
GO

Voir le résultat :

DBCC SQLPERF (LOGSPACE)

Le seul moyen dans Transact-SQL d'examiner la quantité de journal utilisée est DBCC SQLPERF. La syntaxe de la commande est :

DBCC SQLPERF
(
     [ LOGSPACE ]
     |
          [ "sys.dm_os_latch_stats" , CLEAR ]
     |
     [ "sys.dm_os_wait_stats" , CLEAR ]
)
     [WITH NO_INFOMSGS ]

La commande renvoie un jeu de résultats avec une ligne par base de données :

  • Nom de la base de données
  • Taille du journal (Mo)
  • Espace journal utilisé (%)
  • Statut :toujours défini sur zéro

Dans mon environnement, la commande suivante :

DBCC SQLPERF (LOGSPACE);
GO

Renvoie le résultat suivant :

Dans le prochain article, nous allons examiner les enregistrements de journal.