Comment restaurer un lot de journaux de transactions plutôt qu'un par un


11

J'ai une base de données SQL Server qui sauvegarde les journaux de transactions toutes les 10 minutes, avec une sauvegarde complète pendant la nuit.

En utilisant SQL 2008 Management Studio, nous semblons devoir sélectionner chaque journal de transactions un par un. Existe-t-il un moyen de le pointer vers un répertoire?

J'envisage d'exécuter une sauvegarde différentielle plusieurs fois par jour, ce qui peut compenser une partie de cela, mais parcourir une à une des dizaines / centaines de fichiers semble prendre beaucoup de temps. Écrire du code pour essayer de l'écrire semble bien trop éloigné du sujet de nos compétences de base.

Si SQL Server Management Studio ne dispose pas d'un moyen plus rapide, peut-être qu'un outil tiers est disponible?


oui, si tout le mécanisme possible ne fonctionne pas, il vaut mieux demander l'aide de l'outil de récupération de journal SQL sqlserverlogexplorer.com/restore
Jason Clark

Réponses:


10

Il n'existe aucun moyen de spécifier un ensemble de sauvegardes du journal des transactions (dossier oк) à restaurer dans SQL Server Management Studio.

Mais vous pouvez trouver toutes les informations sur les opérations de sauvegarde SQL Server dans la base de données MSDB (jeu de sauvegarde de table et connexes).

Voici un script pour générer des commandes SQL Server pour restaurer la base de données à partir de la sauvegarde et appliquer toutes les sauvegardes des journaux de transactions effectuées à partir de la dernière sauvegarde complète de la base de données. Je pense que cela devrait vous aider.

DECLARE @databaseName sysname
DECLARE @backupStartDate datetime
DECLARE @backup_set_id_start INT
DECLARE @backup_set_id_end INT

-- set database to be used
SET @databaseName = '<your_database_name_here>' 

SELECT @backup_set_id_start = MAX(backup_set_id) 
FROM  msdb.dbo.backupset 
WHERE database_name = @databaseName AND type = 'D'

SELECT @backup_set_id_end = MIN(backup_set_id) 
FROM  msdb.dbo.backupset 
WHERE database_name = @databaseName AND type = 'D'
AND backup_set_id > @backup_set_id_start

IF @backup_set_id_end IS NULL SET @backup_set_id_end = 999999999

SELECT backup_set_id, 'RESTORE DATABASE ' + @databaseName + ' FROM DISK = ''' 
               + mf.physical_device_name + ''' WITH NORECOVERY'
FROM    msdb.dbo.backupset b,
           msdb.dbo.backupmediafamily mf
WHERE    b.media_set_id = mf.media_set_id
           AND b.database_name = @databaseName
          AND b.backup_set_id = @backup_set_id_start
UNION
SELECT backup_set_id, 'RESTORE LOG ' + @databaseName + ' FROM DISK = ''' 
               + mf.physical_device_name + ''' WITH NORECOVERY'
FROM    msdb.dbo.backupset b,
           msdb.dbo.backupmediafamily mf
WHERE    b.media_set_id = mf.media_set_id
           AND b.database_name = @databaseName
          AND b.backup_set_id >= @backup_set_id_start AND b.backup_set_id < @backup_set_id_end
          AND b.type = 'L'
UNION
SELECT 999999999 AS backup_set_id, 'RESTORE DATABASE ' + @databaseName + ' WITH RECOVERY'
ORDER BY backup_set_id

1
Fonctionne vraiment bien si vous pouvez exécuter ce script sur le serveur d'origine mais que vous souhaitez restaurer sur un autre serveur!
realMarkusSchmidt


@sergey: vous devez attribuer des scripts que vous soulevez du Web! : mssqltips.com/sqlservertip/1243/…
Mitch Wheat

4

vous avez juste besoin d'une liste d'instructions sql comme ...

RESTORE LOG AdventureWorks FROM DISK = 'C:\AdventureWorks_1.TRN' WITH NORECOVERY
GO
RESTORE LOG AdventureWorks FROM DISK = 'C:\AdventureWorks_2.TRN'
GO

Vous pouvez donc créer un script VB qui génère facilement ce SQL pour vous à partir d'un dossier donné. Voici un exemple http://blogs.lessthandot.com/index.php/DataMgmt/DBAdmin/MSSQLServerAdmin/restoring-multiple-transaction-log-backu

Une fois qu'il a créé le SQL, il vous suffit de vérifier qu'il semble correct et de l'exécuter.



1

Je ne voulais pas utiliser l'approche basée sur SQL de la réponse acceptée, car je ne voulais pas activer les procédures stockées étendues. J'ai donc écrit un script PowerShell pour le faire.

Vous le pointez sur un dossier et il génère un script basé sur la sauvegarde complète la plus récente et toutes les sauvegardes de journaux de transactions suivantes.

    [System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms")

    $foldername = New-Object System.Windows.Forms.FolderBrowserDialog
    $foldername.rootfolder = "MyComputer"
    $foldername.ShowNewFolderButton = $false
    $foldername.SelectedPath = "E:\DatabaseBackups"

    if($foldername.ShowDialog() -eq "OK") {
        $backupPath = Get-Item($foldername.SelectedPath)    
        $databaseName = $backupPath.Name

        Write-Host($backupPath)
        Write-Host($databaseName)

        $transactionLogFiles = New-Object System.Collections.ArrayList;
        $outputFile = "Restore Database - Script.sql"
        $backupFile;


        foreach ($file in  get-childitem ($backupPath) | sort-object LastWriteTime -descending)
        {
            if ($file.Extension -eq '.trn')
            {
                [void]$transactionLogFiles.Add($file);
            }
            elseif ($file.Extension -eq '.bak')
            {
                $backupFile = $file;
                break;
            }
        }


        Set-Content $outputFile ""

        Add-Content $outputFile "USE master"
        Add-Content $outputFile "ALTER DATABASE $databaseName SET SINGLE_USER WITH ROLLBACK AFTER 5"
        Add-Content $outputFile "RESTORE DATABASE $databaseName FROM DISK = '$($backupFile.FullName)' WITH NORECOVERY";

        foreach ($file in $transactionLogFiles | sort-object LastWriteTime)
        {
            Add-Content $outputFile "RESTORE LOG $databaseName FROM DISK = '$($file.FullName)' WITH NORECOVERY";    
        }

        Add-Content $outputFile "RESTORE DATABASE $databaseName WITH RECOVERY";
        Add-Content $outputFile "ALTER DATABASE $databaseName SET MULTI_USER";
        Add-Content $outputFile "USE $databaseName" 

        Write-Host("Script generated at $outputFile");
        Write-Host "Press any key to continue ..."
        $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
        Invoke-Item $outputFile

    }

Je vous remercie! Vous venez de sauver mon bacon d'un feu chaud et chaud ... msdb était corrompu, il fallait donc le restaurer à partir de la sauvegarde et ne disposait pas des informations de la chaîne de journal. Votre script m'a évité d'avoir à créer les scripts de restauration du journal des transactions à la main en fonction du nom de fichier!
agrath

Et si vous voulez une seule base de données et tous les journaux de transactions? De quoi auriez-vous besoin de changer dans le script?
user493592

Voilà ce que ça fait. Une base de données (la plus récente) et tous les journaux de transactions depuis lors. Il est inutile de consulter les journaux de transactions avant la sauvegarde complète.
Ben Curthoys
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.