Tout DBA se doit de disposer d’une boite à outil prête à l’emploi pour répondre le plus rapidement à une série de problèmes susceptibles de se produire.
Combien de fois vous a-t-on demandé de restaurer une base de données ? Rapidement, très rapidement, car la prod est plantée. Ou bien restaurer la base de production vers l’environnement d’intégration. Ou encore restaurer une copie de base de données à un point précis dans le temps, histoire de vérifier les données à ce moment (alors que la fonctionnalité Temporal Table est disponible – je dis ça je ne dis rien …). Ce n’est pas à ce moment-là qu’il faut se poser des questions sur comment faire. Utiliser ou non l’assistant fourni dans SSMS …
Pour rappel, l’assistant SSMS vous permet de faire un restaure Database de manière très simple. Deux sources possibles : l’historique des sauvegardes et un device, un backup en fait.

J’avoue que je ne suis pas fan de cette option. Et pour plusieurs raisons. La première : l’assistant utilisé avec l’historique des sauvegardes est inopérant lorsque votre base est mise en HA dans un groupe de disponibilité. Les backups peuvent s’effectuer sur le réplica primaire, tout comme n’importe lequel des secondaires (je ne vais pas rentrer dans le détail de FULL COPY_ONLY et des DIFF). Mais la base MDSB n’st pas (encore) « répliquée » sur tous els réplicas d’un AG. Donc l’assistant devient inutilisable.
Tout comme il est inutilisable si vous avez « oublié » de purger les historiques et que SSMS doit scanner la table Backupset sur 10 ans d’historiques ….
Pour contrer ce genre de problèmes, on peut utiliser la notion de Device en tant que source, autrement dit des fichiers de sauvegarde. Vous pouvez ainsi sélectionner 1 ou N fichiers, voire tous les fichiers d’un répertoire, et SSMS va effectuer des RESTORE HEADERONLY et RESTORE FILELISTONLY pour reconstituer la bonne séquence de restauration. Il m’est fréquemment arrivé de crasher SSMS lorsque des centaines de fichiers sont concernés (imaginez juste un backup toutes les minutes, sur 1 semaine …).
Donc encore une fois, le jour où cela se produit et que vous n’avez pas de plan B, vous risquez de suer à grosses gouttes …
C’est pour cela que depuis des années j’avais construit des scripts PowerShell de restaure de base, avec toutes les options imaginables pour me simplifier la vie.
Et puis dbaTools est arrivé, en proposant une commande restore-dbaDatabase … J’ai donc jeté une partie de mes scripts pour basculer sur ce cmdlet.
Restaurer plusieurs bases de données sur une même instance, par exemple depuis le serveur de production vers le serveur d’intégration peut être extrêmement chronophage, surtout si vous avez des dizaines, voire des centaines de bases à traiter. La commande ci-dessous vous permet de restaurer toutes les bases contenues dans les backups présents dans un répertoire et de déplacer les fichiers de DATA et LOG au moment du restore, l’option MOVE TO, pour parer à des éventuelles différences de structure disque entre les serveurs source et destination.
# List of backup files
$backupPath = "\\Rebond\backup\MultipleDatabases"
Get-ChildItem -Path $backupPath
# Restore multiple databases at once - the quickest way
Restore-DbaDatabase -SqlInstance SQL15AG1 `
-Path $backupPath `
-UseDestinationDefaultDirectories
# list databases
get-dbaDatabase -SqlInstance SQL15AG1 -ExcludeSystem | format-table -autosize
Parfois on est amené à effectuer une restauration d’une base vers plusieurs instances. Le script suivant permet à la fois de déplacer les fichiers sur des emplacement spécifiques, mais aussi d’obtenir les scripts de restauration, avant de l’exécuter sur différentes instances.
# Restore single databases on different location on multiple instances
$backupPath = "\\Rebond\backup\AdventureWorks"
Get-ChildItem -Path $backupPath
$tSQL = Get-ChildItem -Path $backupPath `
| Select-Object -First 1 `
| Restore-DbaDatabase -SqlInstance SQL15AG1 `
-DestinationDataDirectory G:\MSSQL15.MSSQLSERVER\MSSQL\DATA `
-DestinationLogDirectory H:\MSSQL15.MSSQLSERVER\Log `
-WithReplace `
-NoRecovery `
-OutputScriptOnly
Write-Host $tSQL
Invoke-DbaQuery -SqlInstance SQL15AG1,SQL15AG2 `
-Query $tSQL
# list databases
get-dbaDatabase -SqlInstance SQL15AG1,SQL15AG2 -ExcludeSystem | format-table -autosize
Et enfin un dernier exemple qui permet de restaurer une copie d’une base de données à un point précis dans le temps, en ajoutant un préfixe au nom de la base ainsi qu’aux fichiers. On présume également que la structure des dossiers de sauvegarde suit la solution de maintenance de Ola Hallengren.
# Restore a copy of a database at a specific point in time
$BackupPath = "\\Rebond\backup\AdventureworksLT"
Get-ChildItem -Path $backupPath -Recurse -Directory # looks like OH folder structure 🙂
Get-ChildItem -Path $backupPath -Recurse
$RestoreTime = Get-Date('16:20 20/02/2021')
$RestoredDatabaseNamePrefix = $RestoreTime.ToString("yyyyMMdd_HHmmss_")
$Result = Restore-DbaDatabase -SqlInstance SQL15AG1 `
-Path $BackupPath `
-UseDestinationDefaultDirectories `
-MaintenanceSolutionBackup `
-RestoredDatabaseNamePrefix $RestoredDatabaseNamePrefix `
-DestinationFilePrefix $RestoredDatabaseNamePrefix `
-RestoreTime $RestoreTime `
-WithReplace
$Result | Select-Object Database, BackupFile, FileRestoreTime, DatabaseRestoreTime | Format-Table -AutoSize
Write-Host "Time taken to restore $($Result[$Result.count - 1].Database) database : $($Result[$Result.count - 1].DatabaseRestoreTime) ($($Result.count) files)"
# list databases
get-dbaDatabase -SqlInstance SQL15AG1 -ExcludeSystem | format-table -autosize
Bref, vous aurez compris qu’au travers de quelques lignes de code extrêmement simples vous pouvez restaurer des bases de données comme vous le souhaitez sans vous soucier du « bon » fonctionnement de SSMS.
Happy dbaTools !
bien