Les requêtes de cette page lisent des informations de l'instance sans modifier vos données. Les commandes qui modifient quelque chose sont signalées dans le texte. Testez toujours sur un environnement non critique avant la production, et relisez chaque requête avant de l'exécuter.
Ce qu'il faut savoir avant
- L'historique des sauvegardes est stocké dans
msdb, instance par instance (tablesbackupsetetrestorehistory). - Sur un réplica secondaire, seules les sauvegardes complètes en copie seule (
COPY_ONLY) et les sauvegardes de journal sont possibles. Les sauvegardes différentielles ne le sont pas. - Le groupe de disponibilité peut indiquer le réplica préféré pour les sauvegardes. La fonction
sys.fn_hadr_backup_is_preferred_replicapermet à un job de sauvegarde de savoir s'il doit s'exécuter.
1. Sur l'instance locale : derniers backups de chaque base
-- Derniers backups par base, sur l'instance où le script est exécuté
-- Droit requis : lecture de msdb. Pour un groupe de disponibilité, voir aussi la partie 3.
SET NOCOUNT ON;
SELECT
d.name AS base,
d.state_desc AS etat,
d.recovery_model_desc AS modele_recuperation,
ag.name AS groupe_disponibilite,
ars.role_desc AS role_local,
CASE WHEN ag.name IS NOT NULL
THEN sys.fn_hadr_backup_is_preferred_replica(d.name) END AS replica_prefere_backup,
(SELECT MAX(b.backup_finish_date) FROM msdb.dbo.backupset AS b
WHERE b.database_name = d.name AND b.server_name = @@SERVERNAME
AND b.type = 'D' AND b.is_copy_only = 0) AS dernier_full,
(SELECT MAX(b.backup_finish_date) FROM msdb.dbo.backupset AS b
WHERE b.database_name = d.name AND b.server_name = @@SERVERNAME
AND b.type = 'D' AND b.is_copy_only = 1) AS dernier_full_copie_seule,
(SELECT MAX(b.backup_finish_date) FROM msdb.dbo.backupset AS b
WHERE b.database_name = d.name AND b.server_name = @@SERVERNAME
AND b.type = 'I') AS dernier_differentiel,
(SELECT MAX(b.backup_finish_date) FROM msdb.dbo.backupset AS b
WHERE b.database_name = d.name AND b.server_name = @@SERVERNAME
AND b.type = 'L') AS dernier_journal
FROM sys.databases AS d
LEFT JOIN sys.dm_hadr_database_replica_states AS drs
ON drs.database_id = d.database_id AND drs.is_local = 1
LEFT JOIN sys.availability_groups AS ag
ON ag.group_id = drs.group_id
LEFT JOIN sys.dm_hadr_availability_replica_states AS ars
ON ars.replica_id = drs.replica_id AND ars.is_local = 1
WHERE d.name <> N'tempdb'
ORDER BY d.name;2. Dernier restore de chaque base
-- Dernier restore enregistré pour chaque base de cette instance
SET NOCOUNT ON;
;WITH r AS (
SELECT
rh.destination_database_name AS base,
rh.restore_date AS date_restore,
rh.user_name AS utilisateur,
CASE rh.restore_type WHEN 'D' THEN 'Complet'
WHEN 'I' THEN 'Différentiel'
WHEN 'L' THEN 'Journal'
WHEN 'F' THEN 'Fichier'
WHEN 'G' THEN 'Groupe de fichiers'
WHEN 'V' THEN 'Vérification seule'
ELSE rh.restore_type END AS type_restore,
bs.server_name AS serveur_source,
bs.database_name AS base_source,
bs.backup_finish_date AS sauvegarde_du,
ROW_NUMBER() OVER (PARTITION BY rh.destination_database_name
ORDER BY rh.restore_date DESC) AS rang
FROM msdb.dbo.restorehistory AS rh
LEFT JOIN msdb.dbo.backupset AS bs
ON bs.backup_set_id = rh.backup_set_id
)
SELECT base, date_restore, utilisateur, type_restore, serveur_source, base_source, sauvegarde_du
FROM r
WHERE rang = 1
ORDER BY base;Un restore de vérification (type « Vérification seule ») ne prouve pas que la base est restaurable : il contrôle l'en-tête de la sauvegarde. Pour une preuve réelle, restaurez la base sur un serveur de test.
3. Tous les réplicas d'un groupe de disponibilité
Cette variante interroge chaque réplica par un serveur lié. Elle suppose qu'un serveur lié existe pour chaque réplica, avec le même nom que le réplica (colonne replica_server_name), et que l'option RPC est activée si vous voulez l'étendre.
-- Derniers backups d'une base sur tous les réplicas de son groupe de disponibilité
SET NOCOUNT ON;
DECLARE @Base sysname = N'MaBase';
DECLARE @sql nvarchar(max) = N'';
-- Réplica local
SET @sql = N'SELECT @@SERVERNAME AS replica, b.database_name AS base, b.type, b.is_copy_only,
MAX(b.backup_finish_date) AS dernier_backup
FROM msdb.dbo.backupset AS b
WHERE b.database_name = @Base AND b.server_name = @@SERVERNAME
GROUP BY b.database_name, b.type, b.is_copy_only';
-- Autres réplicas (serveurs liés portant le nom du réplica)
SELECT @sql += N' UNION ALL SELECT ' + QUOTENAME(ar.replica_server_name, '''')
+ N' AS replica, b.database_name, b.type, b.is_copy_only, MAX(b.backup_finish_date)
FROM ' + QUOTENAME(ar.replica_server_name) + N'.msdb.dbo.backupset AS b
WHERE b.database_name = @Base AND b.server_name = ' + QUOTENAME(ar.replica_server_name, '''')
+ N' GROUP BY b.database_name, b.type, b.is_copy_only'
FROM sys.availability_replicas AS ar
JOIN sys.availability_databases_cluster AS adc
ON adc.group_id = ar.group_id AND adc.database_name = @Base
WHERE ar.replica_server_name <> @@SERVERNAME;
SET @sql = N'SELECT replica, base,
CASE type WHEN ''D'' THEN CASE WHEN is_copy_only = 1 THEN ''Full (copie seule)'' ELSE ''Full'' END
WHEN ''I'' THEN ''Différentiel''
WHEN ''L'' THEN ''Journal'' END AS type_backup,
dernier_backup
FROM (' + @sql + N') AS t
WHERE type IN (''D'', ''I'', ''L'')
ORDER BY base, type, replica';
EXEC sys.sp_executesql @sql, N'@Base sysname', @Base = @Base;- Le plus récent backup, tous réplicas confondus, détermine si la base est protégée. Vérifiez que la chaîne de journaux est continue : un journal sauvegardé sur le secondaire fait partie de la même chaîne que ceux du principal.
- Si la lecture d'un réplica échoue, vérifiez la configuration des serveurs liés et la connectivité.
- Dans un monitoring, alertez sur le plus ancien des derniers backups de journal, pas seulement sur la date du dernier full.