Sauvegardes du journal des transactions SQL Server: testez si le journal de queue suit la dernière sauvegarde de journal connue

11

Nous utilisons SQL Server avec le mode de récupération complète. Étant donné une sauvegarde complète et une série de sauvegardes de journaux, nous aimerions pouvoir vérifier si la chaîne de journaux est complète depuis la dernière sauvegarde complète jusqu'au journal de queue actuel. (Sans réellement restaurer ces sauvegardes; le but ici est de tester la cohérence des sauvegardes.)

Je sais déjà comment procéder pour les sauvegardes existantes: en utilisant RESTORE HEADERONLY, j'obtiens le FirstLSN et le LastLSN de chaque fichier, qui peuvent être comparés pour des fichiers consécutifs, afin de déterminer s'ils sont compatibles.

Cependant, je ne sais pas comment vérifier si le journal de queue suit la dernière sauvegarde du journal.

Si j'avais le FirstLSN du journal de queue, je pourrais le comparer au LastLSN de la dernière sauvegarde du journal. Mais comment puis-je obtenir le FirstLSN du journal de queue?

J'ai besoin d'une solution qui fonctionne à partir de SQL Server 2005 (en utilisant idéalement t-sql). Jusqu'à présent, j'ai cherché sur Google en vain. Btw. J'ai d'abord publié ceci sur stackoverflow; mais il a migré ici car il a été signalé hors sujet là-bas.

ÉDITER

J'ai essayé les deux solutions fournies sur un petit exemple (SQL Server 2005, 9.0.5057):

BACKUP DATABASE TestDb TO DISK = 'C:\temp\backup test\Full.bak' 

-- fire some update queries

BACKUP LOG TestDb TO DISK =  'C:\temp\backup test\Log1.bak' 

-- fire both queries from the provided answers: 
-- Martin Smith's answer yields: 838886656088920652852608
-- Shawn Melton's answer yields: 46000000267600001

RESTORE HEADERONLY FROM DISK = 'C:\temp\backup test\Log1.bak'  
-- yields: 46000000267600001

Il semble donc que le premier soit décalé de plusieurs ordres de grandeur.

J'ai ensuite fait le même test sur SQL 2008 SP1 (10.00.2531), où les deux requêtes ont donné la bonne réponse.

Andreas
la source
J'ai fait des recherches parce que c'est une question intéressante, mais je ne vais pas très loin. Je ne suis pas sûr que SQL prenne cela en charge.
Katherine Villyard
1
Je suis certain qu'il existe un moyen de vérifier cela, peut-être que l'utilisation du LSN n'est pas la façon de le faire. Je mettrai une prime sur la question dans quelques heures, cette question a besoin de plus de vues ..

Réponses:

12

Je me suis tourné vers ma copie de SQL Server 2008 Internals et le DMV sys.database_recovery_status a été signalé pour trouver le premier LSN de la prochaine sauvegarde du journal. Quel passe par BOL la colonne last_log_backup_lsnvous fournit:

Numéro de séquence du journal de la sauvegarde de journal la plus récente. Il s'agit du LSN de fin de la sauvegarde de journal précédente et du LSN de début de la sauvegarde de journal suivante.
NULL = Aucune sauvegarde de journal n'existe. La base de données est hors ligne ou la base de données ne démarre pas.

Juste pour mentionner également que Kalen évoque également le fait que vous obtiendrez une valeur NULL si la base de données est en mode de récupération SIMPLE (mode autotruncate) ou s'il n'existe aucune sauvegarde de journal.

Mais comment puis-je obtenir le FirstLSN du journal de queue?

Sans réellement sauvegarder le journal de fin d'une base de données (ne pas avoir d'instance de test pour l'essayer), vous pouvez logiquement conclure que la valeur retournée dans la colonne mentionnée serait le premier LSN de la prochaine sauvegarde de journal, dans votre cas, le queue.

Donc, l'exécution de ce qui suit retournera la valeur que vous recherchez:


SELECT 
   last_log_backup_lsn
FROM 
   sys.database_recovery_status
WHERE 
   databse_id = DB_ID('MyDb')

Ce DMV est disponible à partir de SQL 2005.

EDIT
Sauf si vous lisez le lien BOL, veuillez noter que ce DMV ne renverra que des valeurs aux bases de données en ligne, ou ouvertes comme BOL le référencent. Si une défaillance se produit qui vous oblige à effectuer une sauvegarde du journal de fin d'une base de données, vous ne pourrez pas vérifier cette valeur via le code ci-dessus, sauf si la base de données est accessible; ce qui, en cas d'échec, ne le serait probablement pas.


la source
Le résultat de cette requête semble être correct.
Andreas
Cela me semble certainement correct. Le last_log_backup_lsn est égal au first_lsn de la queue du journal. Donc, si vous avez un fichier journal à restaurer avec un last_lsn égal au last_log_backup_lsn du code de Shawn, alors vous savez que vous avez une sauvegarde jusqu'au journal de queue. (Bien sûr, cela n'est garanti qu'au moment de la requête, l'instant suivant une nouvelle sauvegarde du journal pourrait être lancée.)
RLF
@RLF a ajouté une note supplémentaire car cela serait également vrai si la base de données n'est pas accessible. Ce n'est pas vraiment une solution viable à utiliser lorsque vous devez mettre en œuvre votre plan de reprise après sinistre. Purement pour les exercices sur table ou pour tester votre plan.
6

Quelque chose comme ce qui suit devrait le faire.

WITH LSN_CTE
AS
(
SELECT TOP 1
       LEFT( LogRecords.[Current LSN], 8 )          AS Part1,
       SUBSTRING( LogRecords.[Current LSN], 10, 8 ) AS Part2,
       RIGHT( LogRecords.[Current LSN], 4 )         AS Part3
FROM   sys.fn_dblog(NULL,NULL) AS LogRecords
ORDER BY [Current LSN]
)
SELECT CAST( CAST( CONVERT( varbinary, Part1, 2 ) AS int ) AS varchar ) +
       RIGHT( '0000000000' + CAST( CAST( CONVERT( varbinary, Part2, 2 ) AS int ) AS varchar ), 10 ) +
       RIGHT( '00000'      + CAST( CAST( CONVERT( varbinary, Part3, 2 ) AS int ) AS varchar ), 5 ) AS [Converted LSN]
FROM   LSN_CTE

Utilisation du code de conversion en décimal de cet article .

Les ORDER BY [Current LSN]frais généraux peuvent être complètement inutiles. Je ne suis pas sûr. Le résultat de cette fonction semble toujours être dans l'ordre LSN et je suppose qu'il lit simplement le journal séquentiellement mais juste au cas où ...

Martin Smith
la source
@MartinSmith: fn_dblogne semble pas très bien documenté. Je suppose que ses résultats sont toujours valables pour la base de données actuelle (car il n'y WHERE DbName = 'XXX'en a pas dans l'extrait)?
Andreas
@Andreas - Oui, ce n'est pas documenté. Et oui, il renvoie les informations du journal de la base de données actuelle.
Martin Smith
voir ma modification à la question d'origine. Le nombre renvoyé par votre extrait est beaucoup plus important que les LSN des sauvegardes récentes de la même base de données.
Andreas
@Andreas - Strange. Je ne l'ai essayé que sur une seule base de données de test et cela a fonctionné correctement. Je ne sais pas où est l'erreur. Sur quelle version de SQL Server utilisez-vous cela? Le CONVERTparamètre with style 2pourrait être le problème.
Martin Smith
(Bien que la réponse de Shawn semble massivement préférable à celle-ci de toute façon)
Martin Smith