Présentation
Vous pouvez trouver de nombreux guides sur la façon de sauvegarder et de restaurer des bases de données. Dans celui-ci, nous montrerons comment cela peut être fait en utilisant les moyens par défaut de MS SQL Server.
Cet exemple couvrira un certain nombre d'approches - de la vérification de l'intégrité de la base de données avant de la sauvegarder à la restauration de la base de données à partir d'une copie de sauvegarde créée précédemment.
La solution
Tout d'abord, examinons l'algorithme global que nous utiliserons pour sauvegarder une base de données :
1) Définir quelles bases de données doivent être sauvegardées
2) Vérifier l'intégrité des bases de données choisies
3) Créer une sauvegarde (complète, différentielle ou copie du journal des transactions) pour chacune des bases de données choisies
4) Vérification des copies de sauvegarde créées
5) Compression des journaux de transactions (si nécessaire)
Ci-dessous, vous trouverez un exemple d'implémentation de cet algorithme.
Pour définir quelles bases de données doivent être sauvegardées, nous allons créer le tableau suivant :
USE [DB_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE TABLE [srv].[BackupSettings]( [DBID] [int] NOT NULL, [FullPathBackup] [nvarchar](255) NOT NULL, [DiffPathBackup] [nvarchar](255 ) NULL, [LogPathBackup] [nvarchar] (255) NULL, [InsertUTCDate] [datetime] NON NULL, CONTRAINTE [PK_BackupSettings] PRIMARY KEY CLUSTERED ( [DBID] ASC)AVEC (PAD_INDEX =OFF, STATISTICS_NORECOMPUTE =OFF, IGNORE_DUP_KEY =OFF, ALLOW_ROW_LOCKS =ON, ALLOW_PAGE_LOCKS =ON) ON [PRIMARY]) ON [PRIMARY];GOALTER TABLE [srv].[BackupSettings] ADD CONSTRAINT [DF_BackupSettings_InsertUTCDate] DEFAULT (getutcdate()) FOR [InsertUTCDate];GO
L'identifiant de la base de données se trouve dans la première colonne, 'FullPathBackup' contient le chemin pour la création d'une copie de sauvegarde complète (par exemple, 'disk:\…\'), et DiffPathBackup et LogPathBackup contiennent des chemins complets pour la création de copies différentielles et de journaux de transactions respectivement. Si les colonnes DiffPathBackup ou LogPathBackup sont vides, la copie différentielle et/ou du journal des transactions pour cette base de données ne sera pas créée.
Nous pouvons également créer une représentation basée sur ce tableau :
USE [DB_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE vue [srv].[vBackupSettings]asSELECT [DBID] ,DB_Name([DBID]) as [DBName] ,[FullPathBackup] ,[DiffPathBackup] ,[LogPathBackup] ,[InsertUTCDate ] DE [srv].[Paramètres de sauvegarde];GO
Cette représentation vous permet de vérifier efficacement quelles bases de données participent au processus de sauvegarde.
Maintenant, créons une représentation qui affiche les informations du fichier de base de données à partir de la représentation système sys.master_files :
USE [DB_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE view [inf].[ServerDBFileInfo] asSELECT @@Servername AS Server , File_id ,--DB file identifier. La valeur de base pour file_id est 1 Type_desc ,--Type file description Name as [FileName] ,--DB logical file name LEFT(Physical_Name, 1) AS Drive ,--Drive flag of the DB file location Physical_Name ,--Full file nom dans le système d'exploitation RIGHT(physical_name, 3) AS Ext ,--File extension Size as CountPage, --Taille actuelle du fichier en pages de 8 Ko round((cast(Size*8 as float))/1024,3) as SizeMb, - -Taille du fichier en Mo round((cast(Size*8 as float))/1024/1024,3) as SizeGb, --File size in Go case when is_percent_growth=0 then Growth*8 else 0 end as Growth, -- Croissance du fichier dans le cas de pages de 8 Ko lorsque is_percent_growth=0 puis arrondi((cast(Growth*8 as float))/1024,3) end as GrowthMb, --File growth in Mb case when is_percent_growth=0 then round((cast(Growth *8 comme float))/1024/1024,3) fin comme GrowthGb, --File growth in Go case when is_percent_growth=1 then Growth else 0 end as GrowthPercent, --File growth in percent is_percent_growth, --Percent growth attribute database_id , DB_ Name(database_id) as [DB_Name], State,--File state state_desc as StateDesc,--File state description is_media_read_only as IsMediaReadOnly,--File is located on the drive as read-only (0 - and for writing) is_read_only as IsReadOnly ,--le fichier est marqué en lecture seule (0 - et pour l'écriture) is_sparse comme IsSpace,--le fichier sparse est_name_reserved comme IsNameReserved,--1 - nom du fichier distant, accessible pour utilisation. --Il est nécessaire d'obtenir une sauvegarde du journal avant d'utiliser à nouveau le même nom (arguments name ou physical_name) pour un nouveau fichier --0 - Nom de fichier, inaccessible pour une utilisation create_lsn comme CreateLsn,--Numéro d'enregistrement de la transaction dans le journal (LSN) qui a été utilisé pour créer le fichier drop_lsn en tant que DropLsn,--LSN qui a été utilisé pour supprimer le fichier read_only_lsn en tant que ReadOnlyLsn,--LSN qui a été utilisé par le groupe de fichiers contenant le fichier pour changer le type "lecture et écriture" en "lecture -only" (le dernier changement) read_write_lsn comme ReadWriteLsn,--LSN qui a été utilisé par le groupe de fichiers contenant le fichier pour changer le type "lecture seule" en "lecture et écriture" (le dernier changement) differential_base_lsn comme DifferentialBaseLsn,- -Une base pour les copies de sauvegarde différentielles. Les extensions de données qui ont été modifiées après l'inclusion du LSN dans la sauvegarde différentielle. differential_base_guid as DifferentialBaseGuid,--Identifiant unique de la copie de sauvegarde de base qui sera utilisée pour créer une copie différentielle. different_base_time as DifferentialBaseTime,--L'heure correspondant à different_base_lsn redo_start_lsn as RedoStartLsn,--LSN utilisé pour déterminer le début du prochain rétablissement --Is NULL, sauf dans les cas où state =RESTORING ou state =RECOVERY_PENDING redo_start_fork_guid as RedoStartForkGuid,- -Identifiant unique pour le point de fourche de restauration --la valeur de l'argument first_fork_guid de la prochaine copie de sauvegarde restaurée doit être égale à cette valeur redo_target_lsn en tant que RedoTargetLsn,--LSN qui sert de point d'arrêt pour une restauration en mode "en ligne" dans ce fichier -- Est NULL, sauf dans les cas où state =RESTORING ou state =RECOVERY_PENDING redo_target_fork_guid as RedoTargetForkGuid,--Fourchette de restauration sur laquelle le conteneur peut être restauré. Utilisé avec redo_target_lsn backup_lsn comme BackupLsn--LSN des données les plus récentes ou la sauvegarde différentielle du fichier copyFROM sys.master_files--database_files;GO
Pour créer des copies de sauvegarde complètes, implémentons la procédure stockée suivante :
[expand title =»Code “]
USE [DB_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOALTER PROCEDURE [srv].[RunFullBackupDB] @ClearLog bit=1 --spécifie si la taille du journal des transactions doit être réduiteASBEGIN /* Création d'une copie de sauvegarde complète de la base de données et vérification de l'intégrité de la base de données au préalable */ SET NOCOUNT ON ; declare @dt datetime=getdate(); declare @year int=YEAR(@dt); déclarer @mois int=MOIS(@dt); declare @day int=DAY(@dt); declare @hour int=DatePart(hour, @dt); déclarer @minute int=DatePart(minute, @dt); declare @second int=DatePart(second, @dt); déclarer @pathBackup nvarchar(255); déclarer @pathstr nvarchar(255); déclarer @DBName nvarchar(255); déclarer @backupName nvarchar(255); déclarer @sql nvarchar(max); déclarer @backupSetId comme int ; déclarer @FileNameLog nvarchar(255); déclarer @tbllog table( [DBName] [nvarchar](255) NOT NULL, [FileNameLog] [nvarchar](255) NOT NULL ); déclarer la table @tbl ( [DBName] [nvarchar](255) NOT NULL, [FullPathBackup] [nvarchar](255) NOT NULL ); --Récupération du nom de la base de données et des chemins d'accès complets pour la création d'une copie de sauvegarde complète insérée dans @tbl ( [DBName] ,[FullPathBackup] ) sélectionnez DB_NAME([DBID]) ,[FullPathBackup] à partir de [srv].[BackupSettings] ; --Récupération du nom de la base de données et des noms des journaux de transactions correspondants (car une base de données peut avoir plusieurs journaux) insérez dans @tbllog([DBName], [FileNameLog]) sélectionnez t.[DBName], tt.[FileName] comme [FileNameLog ] de @tbl as t jointure interne [inf].[ServerDBFileInfo] as tt on t.[DBName]=DB_NAME(tt.[database_id]) where tt.[Type_desc]='LOG' ; -- traiter séquentiellement chacune des bases de données que nous avons obtenues précédemment while(exists(select top(1) 1 from @tbl)) begin set @backupSetId=NULL; sélectionnez top(1) @DBName=[DBName], @pathBackup=[FullPathBackup] à partir de @tbl ; set @[email protected]+N'_Full_backup_'+cast(@year as nvarchar(255))+N'_'+cast(@month as nvarchar(255))+N'_'+cast(@day as nvarchar(255))--+N'_' --+cast(@hour as nvarchar(255))+N'_'+cast(@minute as nvarchar(255))+N'_'+cast(@ seconde comme nvarchar(255)); set @[email protected]@sqldat.com+N'.bak' ; --vérification de l'intégrité de la base de données définie @sql=N'DBCC CHECKDB(N'+N''''[email protected]+N''''+N') WITH NO_INFOMSGS' ; exec(@sql); --executing the backup copy creation procedure set @sql=N'BACKUP DATABASE ['[email protected]+N'] TO DISK =N'+N''''[email protected]+N''''+ N' AVEC NOFORMAT, NOINIT, NOM =N'+N''''[email protected]+N''''+ N', CHECKSUM, STOP_ON_ERROR, SKIP, REWIND, COMPRESSION, STATS =10;'; exec(@sql); -- en vérifiant la copie de sauvegarde que nous avons créée, sélectionnez @backupSetId =position from msdb..backupset where [email protected] and backup_set_id=(select max(backup_set_id) from msdb..backupset where [email protected]); set @sql=N'Erreur de vérification. Les informations de copie de sauvegarde pour la base de données "'[email protected]+'" sont introuvables.'; si @backupSetId est null begin raiserror(@sql, 16, 1) end else begin set @sql=N'RESTORE VERIFYONLY FROM DISK =N'+''''[email protected]+N''''+N' AVEC FICHIER ='+cast(@backupSetId as nvarchar(255)); exec(@sql); end --compression des journaux de transactions de la base de données if(@ClearLog=1) begin while(exists(select top(1) 1 from @tbllog where [DBName][email protected])) begin select top(1) @FileNameLog=FileNameLog de @tbllog où [email protected] ; set @sql=N'USE ['[email protected]+N'];'+N' DBCC SHRINKFILE (N'+N''''[email protected]+N''''+N' , 0 , TRONQUER UNIQUEMENT)' ; exec(@sql); supprimer de @tbllog où [email protected] et [email protected] ; end end delete from @tbl where [DBName][email protected]; finENDGO
[/expand]
Selon le code, nous pouvons voir que cette procédure fournit une solution pour les étapes restantes de l'algorithme de création de copie de sauvegarde.
Les procédures qui créent des copies différentielles et des journaux de transactions sont implémentées de la même manière :
[expand title =»Code “]
USE [DB_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOALTER PROCEDURE [srv].[RunDiffBackupDB] @ClearLog bit=1 --spécifie si la taille du journal des transactions doit être réduiteASBEGIN /* Création d'une copie de sauvegarde différentielle de la base de données */ SET NOCOUNT ON; declare @dt datetime=getdate(); declare @year int=YEAR(@dt); déclarer @mois int=MOIS(@dt); declare @day int=DAY(@dt); declare @hour int=DatePart(hour, @dt); déclarer @minute int=DatePart(minute, @dt); declare @second int=DatePart(second, @dt); déclarer @pathBackup nvarchar(255); déclarer @pathstr nvarchar(255); déclarer @DBName nvarchar(255); déclarer @backupName nvarchar(255); déclarer @sql nvarchar(max); déclarer @backupSetId comme int ; déclarer @FileNameLog nvarchar(255); déclarer la table @tbl ( [DBName] [nvarchar](255) NOT NULL, [DiffPathBackup] [nvarchar](255) NOT NULL ); déclarer @tbllog table( [DBName] [nvarchar](255) NOT NULL, [FileNameLog] [nvarchar](255) NOT NULL ); --Récupération du nom de la base de données et des chemins complets pour créer des copies de sauvegarde différentielles insérées dans @tbl ( [DBName] ,[DiffPathBackup] ) sélectionnez DB_NAME([DBID]) ,[DiffPathBackup] à partir de [srv].[BackupSettings] où [DiffPathBackup] est non nulle; --Récupération du nom de la base de données et des noms complets des fichiers journaux de transactions correspondants (car une base de données peut avoir plusieurs journaux) insérez dans @tbllog([DBName], [FileNameLog]) sélectionnez t.[DBName], tt.[FileName] comme [FileNameLog] de @tbl as t jointure interne [inf].[ServerDBFileInfo] as tt on t.[DBName]=DB_NAME(tt.[database_id]) where tt.[Type_desc]='LOG' ; -- traiter séquentiellement chacune des bases de données que nous avons obtenues précédemment while(exists(select top(1) 1 from @tbl)) begin set @backupSetId=NULL; sélectionnez top(1) @DBName=[DBName], @pathBackup=[DiffPathBackup] de @tbl ; set @[email protected]+N'_Diff_backup_'+cast(@year as nvarchar(255))+N'_'+cast(@month as nvarchar(255))+N'_'+cast(@day as nvarchar(255))+N'_' +cast(@hour as nvarchar(255))+N'_'+cast(@minute as nvarchar(255))+N'_'+cast(@second as nvarchar( 255)); set @[email protected]@sqldat.com+N'.bak' ; --vérification de l'intégrité de la base de données définie @sql=N'DBCC CHECKDB(N'+N''''[email protected]+N''''+N') WITH NO_INFOMSGS' ; exec(@sql); --executing the backup procedure set @sql=N'BACKUP DATABASE ['[email protected]+N'] TO DISK =N'+N''''[email protected]+N''''+ N' AVEC DIFFERENTIEL, NOFORMAT, NOINIT, NOM =N'+N''''[email protected]+N''''+ N', CHECKSUM, STOP_ON_ERROR, SKIP, REWIND, COMPRESSION, STATS =10;'; exec(@sql); -- en vérifiant la copie de sauvegarde que nous venons de créer, sélectionnez @backupSetId =position from msdb..backupset where [email protected] and backup_set_id=(select max(backup_set_id) from msdb..backupset where [email protected]); set @sql=N'Erreur de vérification. Les informations de copie de sauvegarde pour la base de données "'[email protected]+'" sont introuvables.'; si @backupSetId est null begin raiserror(@sql, 16, 1) end else begin set @sql=N'RESTORE VERIFYONLY FROM DISK =N'+''''[email protected]+N''''+N' AVEC FICHIER ='+cast(@backupSetId as nvarchar(255)); exec(@sql); end --compression des journaux de transactions de la base de données if(@ClearLog=1) begin while(exists(select top(1) 1 from @tbllog where [DBName][email protected])) begin select top(1) @FileNameLog=FileNameLog de @tbllog où [email protected] ; set @sql=N'USE ['[email protected]+N'];'+N' DBCC SHRINKFILE (N'+N''''[email protected]+N''''+N' , 0 , TRONQUER UNIQUEMENT)' ; exec(@sql); supprimer de @tbllog où [email protected] et [email protected] ; end end delete from @tbl where [DBName][email protected]; finENDGO
[/expand]
Comme la vérification de l'intégrité des bases de données nécessite beaucoup de ressources, nous pouvons l'omettre lors de la création d'une copie de sauvegarde différentielle.
[expand title =»Code “]
USE [DB_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOALTER PROCEDURE [srv].[RunLogBackupDB] @ClearLog bit=1 --spécifie si la taille du journal des transactions doit être réduiteASBEGIN /* Sauvegarde du journal des transactions de la base de données */ SET NOCOUNT ON; declare @dt datetime=getdate(); declare @year int=YEAR(@dt); déclarer @mois int=MOIS(@dt); declare @day int=DAY(@dt); declare @hour int=DatePart(hour, @dt); déclarer @minute int=DatePart(minute, @dt); declare @second int=DatePart(second, @dt); déclarer @pathBackup nvarchar(255); déclarer @pathstr nvarchar(255); déclarer @DBName nvarchar(255); déclarer @backupName nvarchar(255); déclarer @sql nvarchar(max); déclarer @backupSetId comme int ; déclarer @FileNameLog nvarchar(255); déclarer la table @tbl ( [DBName] [nvarchar](255) NOT NULL, [LogPathBackup] [nvarchar](255) NOT NULL ); déclarer @tbllog table( [DBName] [nvarchar](255) NOT NULL, [FileNameLog] [nvarchar](255) NOT NULL ); --Récupération des noms de base de données et des chemins d'accès complets pour créer des copies de sauvegarde des journaux de transactions avec un modèle de récupération non simple (complète ou en bloc). Les bases de données système sont également exclues. Insérez dans @tbl ( [DBName] ,[LogPathBackup] ) sélectionnez DB_NAME(b.[DBID]) ,b.[LogPathBackup] from [srv].[BackupSettings] as b inner join sys.databases as d sur b.[DBID]=d.[database_id] où d.recovery_model<3 et DB_NAME([DBID]) pas dans ( N'master', N'tempdb', N'model', N'msdb', N' ReportServer', N'ReportServerTempDB' ) et [LogPathBackup] n'est pas nul ; --Récupération du nom de la base de données et des noms complets des fichiers journaux de transactions correspondants (car une base de données peut avoir plusieurs journaux) insérez dans @tbllog([DBName], [FileNameLog]) sélectionnez t.[DBName], tt.[FileName] comme [FileNameLog] de @tbl as t jointure interne [inf].[ServerDBFileInfo] as tt on t.[DBName]=DB_NAME(tt.[database_id]) where tt.[Type_desc]='LOG' ; -- traiter séquentiellement chacune des bases de données que nous avons obtenues précédemment while(exists(select top(1) 1 from @tbl)) begin set @backupSetId=NULL; sélectionnez top(1) @DBName=[DBName], @pathBackup=[LogPathBackup] à partir de @tbl ; set @[email protected]+N'_Log_backup_'+cast(@year as nvarchar(255))+N'_'+cast(@month as nvarchar(255))+N'_'+cast(@day as nvarchar(255))+N'_' +cast(@hour as nvarchar(255))+N'_'+cast(@minute as nvarchar(255))+N'_'+cast(@second as nvarchar( 255)); set @[email protected]@sqldat.com+N'.trn' ; --executing the backup procedure set @sql=N'BACKUP LOG ['[email protected]+N'] TO DISK =N'+N''''[email protected]+N''''+ N' AVEC NOFORMAT, NOINIT, NOM =N'+N''''[email protected]+N''''+ N', CHECKSUM, STOP_ON_ERROR, SKIP, REWIND, COMPRESSION, STATS =10;'; exec(@sql); --Vérification de la copie de sauvegarde du journal des transactions que nous venons de créer, sélectionnez @backupSetId =position de msdb..backupset où [email protected] et backup_set_id=(select max(backup_set_id) from msdb..backupset where [email protected]); set @sql=N'Erreur de vérification. Les informations de copie de sauvegarde pour la base de données "'[email protected]+'" sont introuvables.'; si @backupSetId est null begin raiserror(@sql, 16, 1) end else begin set @sql=N'RESTORE VERIFYONLY FROM DISK =N'+''''[email protected]+N''''+N' AVEC FICHIER ='+cast(@backupSetId as nvarchar(255)); exec(@sql); end --compression des journaux de transactions de la base de données if(@ClearLog=1) begin while(exists(select top(1) 1 from @tbllog where [DBName][email protected])) begin select top(1) @FileNameLog=FileNameLog de @tbllog où [email protected] ; set @sql=N'USE ['[email protected]+N'];'+N' DBCC SHRINKFILE (N'+N''''[email protected]+N''''+N' , 0 , TRONQUER UNIQUEMENT)' ; exec(@sql); supprimer de @tbllog où [email protected] et [email protected] ; end end delete from @tbl where [DBName][email protected]; finENDGO
[/expand]
Comme indiqué ci-dessus, la vérification de l'intégrité des bases de données est une tâche gourmande en ressources. Combiné avec le fait que des copies de sauvegarde du journal des transactions doivent généralement être créées assez souvent, cela nous donne une raison d'omettre la vérification de l'intégrité lors de la création d'une copie du journal des transactions.
Veuillez également garder à l'esprit que des copies de sauvegarde complètes des bases de données "maître", "msdb" et "modèle" doivent être effectuées périodiquement.
Pour automatiser le processus de création de copie de sauvegarde, il vous suffit d'appeler les procédures précédemment mises en œuvre dans le planificateur de tâches Windows, les tâches de l'agent ou tout autre service disponible similaire.
Vous devrez définir la fréquence d'appel pour chacune de ces procédures individuellement en fonction des pics de charge, des plateaux d'activité, etc.
L'approche de base est la suivante :
1) Création d'une copie de sauvegarde complète une fois par jour
2) Création de copies de sauvegarde différentielles toutes les 2 à 4 heures
3) Création de copies de sauvegarde du journal des transactions toutes les 5 à 60 minutes
Veuillez garder à l'esprit que les bases de données participent généralement au système d'accès rapide et à sécurité intégrée. Et, si ce dernier utilise des copies de sauvegarde du journal des transactions, il est extrêmement important de ne pas interférer avec la procédure. Plus précisément, cela signifie que les copies du journal des transactions ne doivent pas être créées par plusieurs processus différents - si cela se produit, la séquence de sauvegarde de ces copies sera perdue.
Ici, nous avons vu des exemples de chaque base de données traitée séquentiellement, une à la fois. Cependant, nous pouvons réaliser un traitement parallèle dans un environnement de production, ce qui permet de créer simultanément plusieurs copies de sauvegarde. Cela peut être abordé de différentes manières. Par exemple, en appelant la procédure stockée suivante :
USE [DB_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE PROCEDURE [inf].[RunAsyncExecute]( @sql nvarchar(max), @jobname nvarchar(57) =null, @database nvarchar(128)=null, @owner nvarchar( 128) =null)AS BEGIN/* Exécution de package asynchrone via les travaux de l'Agent RunAsyncExecute - exécution asynchrone de la commande T-SQL ou de la procédure stockée 2012 Antonin Foller, Motobit Software, www.motobit.com http://www.motobit.com/ conseils/detpg_async-execute-sql/ */ SET NOCOUNT ON ; déclarer @id identifiant unique ; --Créer un nom de travail unique si le nom n'est pas spécifié si (@jobname est nul) set @jobname=''; set @jobname =@jobname + '_async_' + convert(varchar(64),NEWID()); si (@owner est nul) set @owner ='sa'; --Create a new job, get job ID execute msdb..sp_add_job @jobname, @[email protected], @[email protected] OUTPUT ; --Spécifiez un serveur de travaux pour le travail execute msdb..sp_add_jobserver @[email protected] ; --Spécifiez une première étape du travail - la commande SQL --(@on_success_action =3 ... Aller à l'étape suivante) exécutez msdb..sp_add_jobstep @[email protected], @step_name='Step1', @command =@sql, @database_name =@database, @on_success_action =3 ; --Spécifiez l'étape suivante du travail - supprimez le travail declare @deletecommand varchar(200); set @deletecommand ='execute msdb..sp_delete_job @job_name='''[email protected]+''''; exécutez msdb..sp_add_jobstep @[email protected], @step_name='Step2', @command =@deletecommand; --Démarrer le travail exécuter msdb..sp_start_job @[email protected] ; FIN ALLER
Ici, l'asynchronisme est obtenu en créant dynamiquement les travaux de l'Agent, en les exécutant et en les supprimant ensuite.
Examinons maintenant l'algorithme général de restauration des bases de données à partir de copies de sauvegarde précédemment créées dans un environnement différent/de test :
1) Définir les bases de données à restaurer et l'emplacement de leurs copies de sauvegarde
2) Restaurer les bases de données
3) Vérifier l'intégrité des bases de données restaurées
Nous allons maintenant examiner une implémentation d'un algorithme qui restaure une base de données à partir d'une copie de sauvegarde complète. Pour une copie différentielle, la procédure est similaire - la seule différence étant qu'une copie de sauvegarde complète doit être restaurée en premier lieu, suivie de la copie différentielle.
Pour définir quelles bases de données doivent être restaurées, ainsi que l'emplacement de leurs copies de sauvegarde, créons deux tables comme indiqué ci-dessous :
USE [DB_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE TABLE [srv].[RestoreSettings]( [DBName] [nvarchar](255) NOT NULL, [FullPathRestore] [nvarchar](255) NOT NULL, [DiffPathRestore] [nvarchar ](255) NOT NULL, [LogPathRestore] [nvarchar](255) NOT NULL, [InsertUTCDate] [datetime] NOT NULL, CONTRAINTE [PK_RestoreSettings] PRIMARY KEY CLUSTERED ( [DBName] ASC)AVEC (PAD_INDEX =OFF, STATISTICS_NORECOMPUTE =OFF , IGNORE_DUP_KEY =OFF, ALLOW_ROW_LOCKS =ON, ALLOW_PAGE_LOCKS =ON) ON [PRIMARY]) ON [PRIMARY];GOALTER TABLE [srv].[RestoreSettings] ADD CONSTRAINT [DF_RestoreSettings_InsertUTCDate] DEFAULT (getutcdate()) FOR [InsertUTCDate];GOIci, le but des colonnes est analogue à celui de la table [srv].[BackupSettings]. La seule différence étant que le chemin complet sera utilisé pour localiser les copies de sauvegarde à restaurer, et non pour en créer de nouvelles.
USE [DB_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE TABLE [srv].[RestoreSettingsDetail]( [Row_GUID] [uniqueidentifier] NOT NULL, [DBName] [nvarchar](255) NOT NULL, [SourcePathRestore] [nvarchar](255 ) NOT NULL, TargetPathRestore [nvarchar](255) NOT NULL, [Ext] [nvarchar](255) NOT NULL, [InsertUTCDate] [datetime] NOT NULL, CONTRAINTE [PK_RestoreSettingsDetail] PRIMARY KEY CLUSTERED ( [Row_GUID] ASC)AVEC ( PAD_INDEX =OFF, STATISTICS_NORECOMPUTE =OFF, IGNORE_DUP_KEY =OFF, ALLOW_ROW_LOCKS =ON, ALLOW_PAGE_LOCKS =ON) ON [PRIMARY]) ON [PRIMARY];GOALTER TABLE [srv].[RestoreSettingsDetail] ADD CONSTRAINT [DF_RestoreSettingsDetail_Row_GUID] DEFAULT (newid()) FOR [Row_GUID];GOALTER TABLE [srv].[RestoreSettingsDetail] AJOUTER UNE CONTRAINTE [DF_RestoreSettingsDetail_InsertUTCDate] DEFAULT (getutcdate()) FOR [InsertUTCDate];GOCette table est nécessaire pour définir les noms de fichiers complets de la base de données en cours de restauration, qui sont ensuite utilisés pour un transfert ultérieur (par exemple, [SourcePathRestore]='Logical file name' et [TargetPathRestore]='disk:\…\Physical file name ', tandis que [Ext]='Extension de fichier')
En fait, nous pouvons définir les noms logiques des fichiers de la base de données à l'aide de la requête suivante :
RESTAURER LE FICHIER UNIQUEMENT A PARTIR DU DISQUE ='disk:\...\backup copy.BAK';Pour obtenir des informations sur les copies de sauvegarde situées dans un fichier, procédez comme suit :
RESTORE HEADERONLYFROM DISK='disk:\...\backup copy.BAK';Ensuite, nous avons une implémentation d'une procédure stockée utilisée pour restaurer une base de données à partir d'une copie de sauvegarde complète et en vérifier l'intégrité des données :
[expand title =»Code “]
USE [DB_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOALTER PROCEDURE [srv].[RunFullRestoreDB]ASBEGIN /* Récupération d'une base de données à partir d'une copie de sauvegarde complète et vérification de l'intégrité de la base de données */ SET NOCOUNT ON; declare @dt datetime=DateAdd(day,-2,getdate()); declare @year int=YEAR(@dt); déclarer @mois int=MOIS(@dt); declare @day int=DAY(@dt); declare @hour int=DatePart(hour, @dt); déclarer @minute int=DatePart(minute, @dt); declare @second int=DatePart(second, @dt); déclarer @pathBackup nvarchar(255); déclarer @pathstr nvarchar(255); déclarer @DBName nvarchar(255); déclarer @backupName nvarchar(255); déclarer @sql nvarchar(max); déclarer @backupSetId comme int ; déclarer @FileNameLog nvarchar(255); déclarer @SourcePathRestore nvarchar(255); déclarer @TargetPathRestore nvarchar(255); déclarer @Ext nvarchar(255); déclarer la table @tbl ( [DBName] [nvarchar](255) NOT NULL, [FullPathRestore] [nvarchar](255) NOT NULL ); déclarer la table @tbl_files ( [DBName] [nvarchar](255) NOT NULL, [SourcePathRestore] [nvarchar](255) NOT NULL, [TargetPathRestore] [nvarchar](255) NOT NULL, [Ext] [nvarchar](255) NON NULL ); --récupération d'une liste de noms de bases de données et des chemins d'accès aux copies de sauvegarde complètes insérées dans @tbl ( [DBName] ,[FullPathRestore] ) sélectionnez [DBName] ,[FullPathRestore] à partir de [srv].[RestoreSettings] ; --récupération d'informations détaillées sur le nouvel emplacement des fichiers de base de données insérés dans @tbl_files ( [DBName] ,[SourcePathRestore] ,[TargetPathRestore] ,[Ext] ) sélectionnez [DBName] ,[SourcePathRestore] ,[TargetPathRestore] ,[Ext] à partir de [ srv].[RestoreSettingsDetail] ; --processing chacune des bases de données que nous avons obtenues précédemment while(exists(select top(1) 1 from @tbl)) begin set @backupSetId=NULL; sélectionnez top(1) @DBName=[DBName], @pathBackup=[FullPathRestore] de @tbl ; set @[email protected]+N'_Full_backup_'+cast(@year as nvarchar(255))+N'_'+cast(@month as nvarchar(255))+N'_'+cast(@day as nvarchar(255))--+N'_' --+cast(@hour as nvarchar(255))+N'_'+cast(@minute as nvarchar(255))+N'_'+cast(@ seconde comme nvarchar(255)); set @[email protected]@sqldat.com+N'.bak' ; --créer une requête de sauvegarde et l'exécuter set @sql=N'RESTORE DATABASE ['[email protected]+N'_Restore] FROM DISK =N'+N''''[email protected]+N''' '+ N' AVEC FICHIER =1,'; while(exists(select top(1) 1 from @tbl_files where [DBName][email protected])) begin select top(1) @SourcePathRestore=[SourcePathRestore], @TargetPathRestore=[TargetPathRestore], @Ext=[Ext] de @tbl_files où [DBName][email protected] ; set @[email protected]+N' MOVE N'+N''''[email protected]+N''''+N' TO N'+N''''[email protected]+N' _Restore.'[email protected]+N''''+N','; supprimer de @tbl_files où [DBName][email protected] et [SourcePathRestore][email protected] et [Ext][email protected] ; end set @[email protected]+N' NOUNLOAD, REPLACE, STATS =5'; exec(@sql); --vérification de l'intégrité de la base de données définie @sql=N'DBCC CHECKDB(N'+N''''[email protected]+'_Restore'+N''''+N') WITH NO_INFOMSGS' ; exec(@sql); supprimer de @tbl où [DBName][email protected] ; finEND[/expand]
Pour spécifier quelle copie de sauvegarde complète doit être utilisée pour la restauration, un nom de fichier spécialement structuré est utilisé :
_Full_backup_ _ _ .bak Pour automatiser ce processus de restauration de base de données, l'appel de la procédure stockée que nous avons implémentée doit être placé dans le planificateur de tâches Windows, les tâches de l'agent ou tout autre service similaire disponible.
Vous pouvez voir les copies de sauvegarde de base de données les plus récentes en utilisant la représentation suivante :
USE [DB_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE VIEW [inf].[vServerLastBackupDB] aswith backup_cte as( select bs.[database_name], backup_type =case bs.[type] when 'D' then 'database' when 'L ' then 'log' when 'I' then 'differential' else 'other' end, bs.[first_lsn], bs.[last_lsn], bs.[backup_start_date], bs.[backup_finish_date], cast(bs.[backup_size] as decimal(18,3))/1024/1024 as BackupSizeMb, rownum =row_number() over ( partition by bs.[database_name], type order by bs.[backup_finish_date] desc ), LogicalDeviceName =bmf.[logical_device_name], PhysicalDeviceName =bmf.[physical_device_name], bs.[server_name], bs.[user_name] FROM msdb.dbo.backupset bs INNER JOIN msdb.dbo.backupmediafamily bmf ON [bs].[media_set_id] =[bmf].[media_set_id]) sélectionnez [nom_serveur] comme [ServerName], [database_name] as [DBName], [user_name] as [USerName], [backup_type] as [BackupType], [backup_start_date] as [BackupStartDate], [backup_finish_date] as [BackupFinishDate], [BackupSizeMb], -- taille non compressée [LogicalDeviceName], [PhysicalDeviceName], [first_lsn] as [FirstLSN], [last_lsn] as [LastLSN]from backup_ctewhere rownum =1 ;Le résultat
Dans ce guide, nous avons examiné la mise en œuvre d'un processus de sauvegarde automatisé sur un serveur et la restauration consécutive sur un autre (un serveur de test, par exemple).
Cette méthode nous permet d'automatiser le processus de création de copie de sauvegarde, de vérifier les copies de sauvegarde en les restaurant et d'affiner les processus indiqués ci-dessus.
Source :
Sauvegarde
Restauration
Ensemble de sauvegarde
CHECKDB
SHRINKFILE
sys.master_files