Inleiding
U kunt veel handleidingen vinden over het maken van back-ups en het herstellen van databases. In deze laten we zien hoe dit kan worden gedaan met behulp van de standaard MS SQL Server-middelen.
Dit voorbeeld behandelt een aantal benaderingen:van het controleren van de integriteit van de database voordat er een back-up van wordt gemaakt tot het herstellen van de database vanaf een eerder gemaakte back-upkopie.
De oplossing
Laten we eerst eens kijken naar het algemene algoritme dat we zullen gebruiken voor het maken van een back-up van een database:
1) Definiëren van welke databases een back-up moet worden gemaakt
2) De integriteit van de gekozen databases controleren
3) Een back-up maken (volledige, differentiële of transactielogboekkopie) voor elk van de gekozen databases
4) De gemaakte reservekopieën controleren
5) De transactielogboeken comprimeren (indien nodig)
Hieronder vindt u een implementatievoorbeeld van dit algoritme.
Om te definiëren van welke databases een back-up moet worden gemaakt, maken we de volgende tabel:
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] NOT NULL, CONSTRAINT [PK_BackupSettings] PRIMARY KEY CLUSTERED ( [DBID] ASC)MET (PAD_INDEX =OFF, STATISTICS_NORECOMPUTE_UP =OFF, IGNORECOMPUTE_UP_KEY =ALLOW_ROW_LOCKS =AAN, ALLOW_PAGE_LOCKS =AAN) OP [PRIMARY]) OP [PRIMARY];GOALTER TABLE [srv].[BackupSettings] ADD CONSTRAINT [DF_BackupSettings_InsertUTCDate] STANDAARD (getutcdate()) FOR [Insertpre>Insert>;De database-ID bevindt zich in de eerste kolom, 'FullPathBackup' bevat het pad voor het maken van een volledige back-upkopie (bijvoorbeeld 'disk:\...\'), en de DiffPathBackup en LogPathBackup bevatten volledige paden voor het maken van differentiële en transactielogboekkopieën respectievelijk. Als de DiffPathBackup- of LogPathBackup-kolommen leeg zijn, wordt de differentiële en/of transactielogkopie voor deze database niet gemaakt.
We kunnen ook een weergave maken op basis van deze tabel:
GEBRUIK [DB_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE weergave [srv].[vBackupSettings]asSELECT [DBID] ,DB_Name([DBID]) als [DBName] ,[FullPathBackup] ,[DiffPathBackupCD] ,[LogPathBackup] ,[LogPathBackup] ,[LogPathBackup] ] FROM [srv].[BackupSettings];GOMet deze weergave kunt u effectief controleren welke databases deelnemen aan het back-upproces.
Laten we nu een weergave maken die databasebestandsinformatie weergeeft van de systeemweergave van sys.master_files:
GEBRUIK [DB_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE view [inf].[ServerDBFileInfo] asSELECT @@Servername AS Server , File_id ,--DB bestandsidentificatie. De basiswaarde voor file_id is 1 Type_desc ,--Type bestandsbeschrijving Naam als [FileName] ,--DB logische bestandsnaam LEFT(Physical_Name, 1) AS Drive ,--Drive-vlag van de DB-bestandslocatie Physical_Name ,--Volledig bestand naam in het OS RIGHT(physical_name, 3) AS Ext ,--File extension Size as CountPage, --Huidige bestandsgrootte in 8Kb pagina's round((cast(Size*8 as float))/1024,3) als SizeMb, - -Bestandsgrootte in Mb round((cast(Size*8 as float))/1024/1024,3) as SizeGb, --File size in Gb case when is_percent_growth=0 then Growth*8 else 0 end as Growth, -- Bestandsgroei in 8Kb-pagina's geval wanneer is_percent_growth=0 dan rond((cast(Growth*8 as float))/1024,3) end as GrowthMb, --Bestandsgroei in Mb geval wanneer is_percent_growth=0 dan rond((cast(Growth *8 as float))/1024/1024,3) eindigen als GrowthGb, --Bestandsgroei in Gb geval wanneer is_percent_growth=1 dan Groei anders 0 eindigen als GrowthPercent, --Bestandsgroei in procent is_percent_growth, --Percentage groei attribuut 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 bevindt zich op de schijf als alleen-lezen (0 - en voor schrijven) is_read_only als IsReadOnly ,--bestand is gemarkeerd als alleen-lezen (0 - en voor schrijven) is_sparse als IsSpace,--Sparse bestand is_naam_reserved als IsNameReserved,--1 - Externe bestandsnaam, toegankelijk voor gebruik. --Het is noodzakelijk om een logback-up te maken voordat u dezelfde naam (naam of fysieke_naam-argumenten) opnieuw gebruikt voor een nieuw bestand --0 - Bestandsnaam, ontoegankelijk voor gebruik create_lsn als CreateLsn, -- Transactieregistratienummer in het log (LSN) dat werd gebruikt om het bestand drop_lsn te maken als DropLsn,--LSN dat werd gebruikt om het bestand read_only_lsn te verwijderen als ReadOnlyLsn,--LSN dat werd gebruikt door de bestandsgroep die het bestand bevat om het type "lezen en schrijven" te wijzigen in "lezen -only" (de laatste wijziging) read_write_lsn als ReadWriteLsn,--LSN dat werd gebruikt door de bestandsgroep die het bestand bevat om het type "alleen-lezen" te wijzigen in "lezen en schrijven" (de laatste wijziging) differential_base_lsn als DifferentialBaseLsn,- -Een basis voor differentiële back-upkopieën. Gegevensbereiken die zijn gewijzigd nadat de LSN is opgenomen in de differentiële back-up. differential_base_guid as DifferentialBaseGuid,--Unieke identificatie van de basisback-up die zal worden gebruikt om een differentiële kopie te maken. differential_base_time als DifferentialBaseTime,--De tijd die overeenkomt met differential_base_lsn redo_start_lsn als RedoStartLsn,--LSN gebruikt om de start van de volgende herhaling te bepalen --Is NULL, behalve in de gevallen waarin state =RESTORING of state =RECOVERY_PENDING redo_start_forkStart_Guid als Redo,- -Unieke id voor het herstelvorkpunt --first_fork_guid argumentwaarde van de volgende herstelde back-upkopie moet gelijk zijn aan deze waarde redo_target_lsn als RedoTargetLsn,--LSN dat dient als een stoppunt voor een "online" modus opnieuw uitvoeren in dit bestand -- Is NULL, behalve in de gevallen waarin state =RESTORING of state =RECOVERY_PENDING redo_target_fork_guid als RedoTargetForkGuid,--Restoration fork waarop de container kan worden hersteld. Gebruikt samen met redo_target_lsn backup_lsn als BackupLsn--LSN van de meest recente gegevens of de differentiële back-up van het bestand copyFROM sys.master_files--database_files;GOLaten we de volgende opgeslagen procedure implementeren om volledige back-upkopieën te maken:
[titel uitbreiden =”Code "]
USE [DB_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOALTER PROCEDURE [srv].[RunFullBackupDB] @ClearLog bit=1 --geeft aan of de transactieloggrootte moet worden verkleindASBEGIN /* Een volledige DB-back-up maken en de DB controleren op integriteit vooraf */ STEL NOCOUNT IN; declareer @dt datetime=getdate(); declareren @jaar int=JAAR(@dt); declareren @maand int=MAAND(@dt); declareren @day int=DAY(@dt); declareren @hour int=DatePart(hour, @dt); declareren @minute int=DatePart(minuut, @dt); declareren @second int=DatePart(second, @dt); declareren @pathBackup nvarchar(255); declareren @pathstr nvarchar(255); declareren @DBName nvarchar(255); declareren @backupName nvarchar(255); declareren @sql nvarchar(max); declareer @backupSetId als int; declareren @FileNameLog nvarchar(255); declare @tbllog table( [DBName] [nvarchar](255) NOT NULL, [FileNameLog] [nvarchar](255) NOT NULL); declareer @tbl-tabel ( [DBName] [nvarchar](255) NOT NULL, [FullPathBackup] [nvarchar](255) NOT NULL); --Ophalen van DB-naam en volledige paden voor het maken van volledige back-upkopieën invoegen in @tbl ( [DBName] ,[FullPathBackup] ) selecteer DB_NAME([DBID]), [FullPathBackup] van [srv].[BackupSettings]; --Ophalen van de DB-naam en namen van de overeenkomstige transactielogboeken (aangezien een DB meerdere logboeken kan hebben) invoegen in @tbllog([DBName], [FileNameLog]) selecteer t.[DBName], tt.[FileName] als [FileNameLog ] van @tbl als t inner join [inf].[ServerDBFileInfo] als tt op t.[DBName]=DB_NAME(tt.[database_id]) waar tt.[Type_desc]='LOG'; --opeenvolgend verwerken van elk van de DB's die we eerder hebben gekregen while(exists(select top(1) 1 from @tbl)) begin set @backupSetId=NULL; selecteer top(1) @DBName=[DBName], @pathBackup=[FullPathBackup] van @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 als nvarchar(255))+N'_'+cast(@minute als nvarchar(255))+N'_'+cast(@ tweede als nvarchar(255)); set @[email protected]@sqldat.com+N'.bak'; --controleren van de DB op integriteit set @sql=N'DBCC CHECKDB(N'+N''''[email protected]+N''''+N') WITH NO_INFOMSGS'; exec(@sql); --het uitvoeren van de procedure voor het maken van een reservekopie set @sql=N'BACKUP DATABASE ['[email protected]+N'] TO DISK =N'+N''''[email protected]+N''''+ N' WITH NOFORMAT, NOINIT, NAME =N'+N''''[email protected]+N''''+ N', CHECKSUM, STOP_ON_ERROR, SKIP, REWIND, COMPRESSION, STATS =10;'; exec(@sql); --controleren van de back-up die we hebben gemaakt selecteer @backupSetId =positie van msdb..backupset waar [email protected] en backup_set_id=(selecteer max(backup_set_id) van msdb..backupset waar [email protected]); set @sql=N'Verificatiefout. Reservekopie-informatie voor "'[email protected]+'" database niet gevonden.'; als @backupSetId null is begin raiserror(@sql, 16, 1) end else begin set @sql=N'RESTORE VERIFYONLY FROM DISK =N'+''''[email protected]+N''''+N' WITH FILE ='+cast(@backupSetId als nvarchar(255)); exec(@sql); end --de DB-transactielogboeken comprimeren if(@ClearLog=1) begin while(exists(select top(1) 1 from @tbllog where [DBName][email protected])) begin select top(1) @FileNameLog=FileNameLog van @tbllog waar [email protected]; set @sql=N'USE ['[email protected]+N'];'+N' DBCC SHRINKFILE (N'+N''''[email protected]+N''''+N' , 0 , ALLEEN AFKOPPEN)'; exec(@sql); verwijderen uit @tbllog waar [email protected] en [email protected]; end end delete from @tbl waar [DBName][email protected]; endENDGO[/uitbreiden]
Volgens de code kunnen we zien dat deze procedure een oplossing biedt voor de resterende stappen van het algoritme voor het maken van back-ups.
Procedures die differentiële en transactielogkopieën maken, worden op een vergelijkbare manier geïmplementeerd:
[titel uitbreiden =”Code "]
USE [DB_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOALTER PROCEDURE [srv].[RunDiffBackupDB] @ClearLog bit=1 --geeft aan of de transactieloggrootte moet worden verkleindASBEGIN /* Een differentiële DB-back-upkopie maken */ STEL NOCOUNT IN; declareer @dt datetime=getdate(); declareren @jaar int=JAAR(@dt); declareren @maand int=MAAND(@dt); declareren @day int=DAY(@dt); declareren @hour int=DatePart(hour, @dt); declareren @minute int=DatePart(minuut, @dt); declareren @second int=DatePart(second, @dt); declareren @pathBackup nvarchar(255); declareren @pathstr nvarchar(255); declareren @DBName nvarchar(255); declareren @backupName nvarchar(255); declareren @sql nvarchar(max); declareer @backupSetId als int; declareren @FileNameLog nvarchar(255); declareer @tbl-tabel ( [DBName] [nvarchar](255) NOT NULL, [DiffPathBackup] [nvarchar](255) NOT NULL); declare @tbllog table( [DBName] [nvarchar](255) NOT NULL, [FileNameLog] [nvarchar](255) NOT NULL); --Ophalen van de DB-naam en volledige paden voor het maken van differentiële back-upkopieën invoegen in @tbl ( [DBName] ,[DiffPathBackup] ) selecteer DB_NAME([DBID]), [DiffPathBackup] van [srv].[BackupSettings] waar [DiffPathBackup] is niet nul; --Ophalen van de DB-naam en de volledige namen van de bijbehorende transactielogbestanden (aangezien een DB meerdere logbestanden kan hebben) invoegen in @tbllog([DBName], [FileNameLog]) selecteer t.[DBName], tt.[FileName] als [FileNameLog] van @tbl als t inner join [inf].[ServerDBFileInfo] als tt op t.[DBName]=DB_NAME(tt.[database_id]) waarbij tt.[Type_desc]='LOG'; --opeenvolgend verwerken van elk van de DB's die we eerder hebben gekregen while(exists(select top(1) 1 from @tbl)) begin set @backupSetId=NULL; selecteer top(1) @DBName=[DBName], @pathBackup=[DiffPathBackup] van @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 als nvarchar(255))+N'_'+cast(@minute als nvarchar(255))+N'_'+cast(@seconde als nvarchar( 255)); set @[email protected]@sqldat.com+N'.bak'; --controleren van de DB op integriteit set @sql=N'DBCC CHECKDB(N'+N''''[email protected]+N''''+N') WITH NO_INFOMSGS'; exec(@sql); --het uitvoeren van de back-upprocedure set @sql=N'BACKUP DATABASE ['[email protected]+N'] TO DISK =N'+N''''[email protected]+N''''+ N' MET DIFFERENTIEEL, NOFORMAT, NOINIT, NAME =N'+N''''[email protected]+N''''+ N', CHECKSUM, STOP_ON_ERROR, SKIP, REWIND, COMPRESSION, STATS =10;'; exec(@sql); --controleer de reservekopie die we zojuist hebben gemaakt selecteer @backupSetId =positie van msdb..backupset waar [email protected] en backup_set_id=(selecteer max(backup_set_id) van msdb..backupset waar [email protected]); set @sql=N'Verificatiefout. Reservekopie-informatie voor "'[email protected]+'" database niet gevonden.'; als @backupSetId null is begin raiserror(@sql, 16, 1) end else begin set @sql=N'RESTORE VERIFYONLY FROM DISK =N'+''''[email protected]+N''''+N' WITH FILE ='+cast(@backupSetId als nvarchar(255)); exec(@sql); end --de DB-transactielogboeken comprimeren if(@ClearLog=1) begin while(exists(select top(1) 1 from @tbllog where [DBName][email protected])) begin select top(1) @FileNameLog=FileNameLog van @tbllog waar [email protected]; set @sql=N'USE ['[email protected]+N'];'+N' DBCC SHRINKFILE (N'+N''''[email protected]+N''''+N' , 0 , ALLEEN AFKOPPEN)'; exec(@sql); verwijderen uit @tbllog waar [email protected] en [email protected]; end end delete from @tbl waar [DBName][email protected]; endENDGO[/uitbreiden]
Omdat het controleren van databases op integriteit veel middelen kost, kunnen we dit achterwege laten terwijl we een differentiële reservekopie maken.
[titel uitbreiden =”Code "]
USE [DB_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOALTER PROCEDURE [srv].[RunLogBackupDB] @ClearLog bit=1 --geeft aan of de transactieloggrootte moet worden verkleindASBEGIN /* Back-up van het DB-transactielogboek */ STEL NOCOUNT IN; declareer @dt datetime=getdate(); declareren @jaar int=JAAR(@dt); declareren @maand int=MAAND(@dt); declareren @day int=DAY(@dt); declareren @hour int=DatePart(hour, @dt); declareren @minute int=DatePart(minuut, @dt); declareren @second int=DatePart(second, @dt); declareren @pathBackup nvarchar(255); declareren @pathstr nvarchar(255); declareren @DBName nvarchar(255); declareren @backupName nvarchar(255); declareren @sql nvarchar(max); declareer @backupSetId als int; declareren @FileNameLog nvarchar(255); declareer @tbl-tabel ( [DBName] [nvarchar](255) NOT NULL, [LogPathBackup] [nvarchar](255) NOT NULL); declare @tbllog table( [DBName] [nvarchar](255) NOT NULL, [FileNameLog] [nvarchar](255) NOT NULL); --Ophalen van DB-namen en volledige paden voor het maken van back-upkopieën van transactielogboeken met een niet-eenvoudig herstelmodel (volledig of bulksgewijs geregistreerd). Systeem-DB's zijn ook uitgesloten. insert into @tbl ( [DBName] ,[LogPathBackup] ) select DB_NAME(b.[DBID]) ,b.[LogPathBackup] from [srv].[BackupSettings] as b inner join sys.databases as d op b.[DBID]=d.[database_id] waar d.recovery_model<3 en DB_NAME([DBID]) niet in ( N'master', N'tempdb', N'model', N'msdb', N' ReportServer', N'ReportServerTempDB' ) en [LogPathBackup] is niet null; --Ophalen van de DB-naam en de volledige namen van de bijbehorende transactielogbestanden (aangezien een DB meerdere logbestanden kan hebben) invoegen in @tbllog([DBName], [FileNameLog]) selecteer t.[DBName], tt.[FileName] als [FileNameLog] van @tbl als t inner join [inf].[ServerDBFileInfo] als tt op t.[DBName]=DB_NAME(tt.[database_id]) waarbij tt.[Type_desc]='LOG'; --opeenvolgend verwerken van elk van de DB's die we eerder hebben gekregen while(exists(select top(1) 1 from @tbl)) begin set @backupSetId=NULL; selecteer top(1) @DBName=[DBName], @pathBackup=[LogPathBackup] van @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 als nvarchar(255))+N'_'+cast(@minute als nvarchar(255))+N'_'+cast(@seconde als nvarchar( 255)); stel @[email protected]@sqldat.com+N'.trn' in; --het uitvoeren van de back-upprocedure set @sql=N'BACKUP LOG ['[email protected]+N'] TO DISK =N'+N''''[email protected]+N''''+ N' MET NOFORMAT, NOINIT, NAME =N'+N''''[email protected]+N''''+ N', CHECKSUM, STOP_ON_ERROR, SKIP, REWIND, COMPRESSION, STATS =10;'; exec(@sql); --Het controleren van de zojuist gemaakte reservekopie van het transactielogboek selecteer @backupSetId =positie van msdb..backupset waar [email protected] en backup_set_id=(selecteer max(backup_set_id) van msdb..backupset waar [email protected]); set @sql=N'Verificatiefout. Reservekopie-informatie voor "'[email protected]+'" database niet gevonden.'; als @backupSetId null is begin raiserror(@sql, 16, 1) end else begin set @sql=N'RESTORE VERIFYONLY FROM DISK =N'+''''[email protected]+N''''+N' WITH FILE ='+cast(@backupSetId als nvarchar(255)); exec(@sql); end --de DB-transactielogboeken comprimeren if(@ClearLog=1) begin while(exists(select top(1) 1 from @tbllog where [DBName][email protected])) begin select top(1) @FileNameLog=FileNameLog van @tbllog waar [email protected]; set @sql=N'USE ['[email protected]+N'];'+N' DBCC SHRINKFILE (N'+N''''[email protected]+N''''+N' , 0 , ALLEEN AFKOPPEN)'; exec(@sql); verwijderen uit @tbllog waar [email protected] en [email protected]; end end delete from @tbl waar [DBName][email protected]; endENDGO[/uitbreiden]
Zoals hierboven vermeld, is het controleren van databases op integriteit een zware taak. In combinatie met het feit dat back-upkopieën van transactielogboeken meestal vrij vaak moeten worden gemaakt, geeft dit ons een reden om integriteitscontrole weg te laten bij het maken van een transactielogboekkopie.
Houd er ook rekening mee dat er regelmatig volledige back-upkopieën van de 'master'-, 'msdb'- en 'model'-databases moeten worden gemaakt.
Om het proces voor het maken van back-ups te automatiseren, hoeft u alleen maar de eerder geïmplementeerde procedures aan te roepen in de Windows Taakplanner, agenttaken of een vergelijkbare beschikbare service.
U moet de oproepfrequentie voor elk van deze procedures afzonderlijk instellen op basis van de belastingspieken, activiteitsplateaus, enz.
De basisbenadering is als volgt:
1) Eén keer per dag een volledige back-upkopie maken
2) Elke 2-4 uur differentiële back-upkopieën maken
3) Elke 5-60 minuten een back-upkopie van het transactielogboek makenHoud er rekening mee dat databases meestal deelnemen aan het faalveilige en snelle toegangssysteem. En als de laatste back-upkopieën van transactielogboeken gebruikt, is het van vitaal belang om de procedure niet te verstoren. Meer specifiek betekent dit dat kopieën van transactielogboeken niet door verschillende processen moeten worden gemaakt - als dit gebeurt, gaat de back-upreeks van deze kopieën verloren.
Hier hebben we voorbeelden gezien van elke database die opeenvolgend wordt verwerkt, één voor één. We kunnen echter parallelle verwerking in de productieomgeving realiseren, waardoor meerdere back-upkopieën tegelijkertijd kunnen worden gemaakt. Dit kan op een aantal verschillende manieren worden benaderd. Bijvoorbeeld door de volgende opgeslagen procedure aan te roepen:
GEBRUIK [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/* Asynchrone pakketuitvoering via de taken van de agent RunAsyncExecute - asynchrone uitvoering van T-SQL-opdracht of opgeslagen prodecure 2012 Antonin Foller, Motobit Software, www.motobit.com http://www.motobit.com/ tips/detpg_async-execute-sql/ */ STEL NOCOUNT IN; declareren @id uniqueidentifier; --Maak een unieke taaknaam als de naam niet is opgegeven als (@taaknaam null is) set @taaknaam=''; set @jobname =@jobname + '_async_' + convert(varchar(64),NEWID()); if (@owner is null) set @owner ='sa'; --Maak een nieuwe taak, haal taak-ID op uitvoeren msdb..sp_add_job @jobname, @[email protected], @[email protected] OUTPUT; --Specificeer een taakserver voor de taakuitvoering msdb..sp_add_jobserver @[email protected]; --Specificeer een eerste stap van de taak - het SQL-commando --(@on_success_action =3 ... Ga naar de volgende stap) execute msdb..sp_add_jobstep @[email protected], @step_name='Step1', @command =@sql, @database_name =@database, @on_success_action =3; --Specificeer de volgende stap van de taak - verwijder de taak declareer @deletecommand varchar(200); set @deletecommand ='voer msdb..sp_delete_job @job_name='''[email protected]+'''' uit; execute msdb..sp_add_jobstep @[email protected], @step_name='Step2', @command =@deletecommand; --Start de taak en voer msdb..sp_start_job @[email protected] uit; EINDE GOHier wordt asynchronie bereikt door het dynamisch creëren van de Agent-taken, ze daarna uit te voeren en te verwijderen.
Laten we nu eens kijken naar het algemene algoritme voor het herstellen van databases van back-ups die eerder in een andere/testomgeving zijn gemaakt:
1) Definiëren welke databases moeten worden hersteld en de locatie van hun reservekopieën
2) De databases herstellen
3) De herstelde databases controleren op integriteitNu zullen we kijken naar een implementatie van een algoritme dat een database herstelt vanaf een volledige back-up. Voor een differentiële kopie is de procedure vergelijkbaar - het enige verschil is dat een volledige reservekopie uit de eerste hand moet worden hersteld, gevolgd door de differentiële kopie.
Laten we, om te bepalen welke databases moeten worden hersteld, evenals de locatie van hun back-upkopieën, twee tabellen maken, zoals hieronder weergegeven:
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, CONSTRAINT [PK_RestoreSettings] PRIMAIRE SLEUTEL GECLUSTERD ([DBName] ASC) MET (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) /pre>Hier is het doel van de kolommen analoog aan die van de [srv].[BackupSettings]-tabel. Het enige verschil is dat het volledige pad wordt gebruikt om de back-upkopieën voor herstel te lokaliseren en niet om nieuwe te maken.
USE [DB_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE TABLE [srv].[RestoreSettingsDetail]( [Row_GUID] [uniqueidentifier] NOT NULL, [DBName] [nvarchar](255) NOT NULL, [SourcePathRestore] [nvarcePathRestore] ) NOT NULL, TargetPathRestore [nvarchar](255) NOT NULL, [Ext] [nvarchar](255) NOT NULL, [InsertUTCDate] [datetime] NOT NULL, CONSTRAINT [PK_RestoreSettingsDetail] PRIMAIRE SLEUTEL GECLUSTERD ( [Row_GUID] ASC) MET ( PAD_INDEX =UIT, STATISTICS_NORECOMPUTE =UIT, IGNORE_DUP_KEY =UIT, ALLOW_ROW_LOCKS =AAN, ALLOW_PAGE_LOCKS =AAN) AAN [PRIMARY]) AAN [PRIMAIR];GOALTER TABLE [srv].[RestoreSettingsDetail] ADDReID CONSTRRAFAINTs FOR [Row_GUID];GOALTER TABLE [srv].[RestoreSettingsDetail] ADD CONSTRAINT [DF_RestoreSettingsDetail_InsertUTCDate] STANDAARD (getutcdate()) FOR [InsertUTCDate];GODeze tabel is nodig om de volledige bestandsnamen te definiëren van de database die wordt hersteld, die vervolgens worden gebruikt voor verdere overdracht (bijvoorbeeld [SourcePathRestore]='Logische bestandsnaam' en [TargetPathRestore]='disk:\…\Physical file name ', while [Ext]='Bestandsextensie')
In feite kunnen we logische namen van de databasebestanden definiëren met behulp van de volgende query:
HERSTEL FILELISTEN ALLEEN VANAF SCHIJF ='disk:\...\backup copy.BAK';Informatie verkrijgen over reservekopieën in een bestand kan op deze manier worden gedaan:
HERSTEL HEADERONLYFROM DISK='disk:\...\backup copy.BAK';Vervolgens hebben we een implementatie van een opgeslagen procedure die wordt gebruikt om een database te herstellen vanaf een volledige back-upkopie en deze te controleren op gegevensintegriteit:
[titel uitbreiden =”Code "]
USE [DB_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOALTER PROCEDURE [srv].[RunFullRestoreDB]ASBEGIN /* Een database herstellen van een volledige back-up en de database controleren op integriteit */ SET NOCOUNT ON; declare @dt datetime=DateAdd(day,-2,getdate()); declareren @jaar int=JAAR(@dt); declareren @maand int=MAAND(@dt); declareren @day int=DAY(@dt); declareren @hour int=DatePart(hour, @dt); declareren @minute int=DatePart(minuut, @dt); declareren @second int=DatePart(second, @dt); declareren @pathBackup nvarchar(255); declareren @pathstr nvarchar(255); declareren @DBName nvarchar(255); declareren @backupName nvarchar(255); declareren @sql nvarchar(max); declareer @backupSetId als int; declareren @FileNameLog nvarchar(255); verklaar @SourcePathRestore nvarchar(255); verklaar @TargetPathRestore nvarchar(255); declareren @Ext nvarchar(255); declareer @tbl-tabel ( [DBName] [nvarchar](255) NOT NULL, [FullPathRestore] [nvarchar](255) NOT NULL); declareer @tbl_files tabel ( [DBName] [nvarchar](255) NOT NULL, [SourcePathRestore] [nvarchar](255) NOT NULL, [TargetPathRestore] [nvarchar](255) NOT NULL, [Ext] [nvarchar](255) NIET NUL ); --het ophalen van een lijst met DB-namen en de paden naar volledige back-upkopieën invoegen in @tbl ( [DBName] ,[FullPathRestore] ) selecteer [DBName] ,[FullPathRestore] van [srv].[RestoreSettings]; -- ophalen van gedetailleerde informatie over de nieuwe DB-bestanden locatie invoegen in @tbl_files ( [DBName] ,[SourcePathRestore] ,[TargetPathRestore] ,[Ext] ) selecteer [DBName] ,[SourcePathRestore] ,[TargetPathRestore] ,[Ext] van [ srv].[RestoreSettingsDetail]; --het verwerken van elk van de DB's die we eerder hebben gekregen while(exists(select top(1) 1 from @tbl)) begin set @backupSetId=NULL; selecteer top(1) @DBName=[DBName], @pathBackup=[FullPathRestore] van @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 als nvarchar(255))+N'_'+cast(@minute als nvarchar(255))+N'_'+cast(@ tweede als nvarchar(255)); set @[email protected]@sqldat.com+N'.bak'; --maak een back-upquery en voer deze uit set @sql=N'RESTORE DATABASE ['[email protected]+N'_Restore] FROM DISK =N'+N''''[email protected]+N''' '+ N' MET BESTAND =1,'; while(exists(select top(1) 1 from @tbl_files where [DBName][email protected])) begin select top(1) @SourcePathRestore=[SourcePathRestore], @TargetPathRestore=[TargetPathRestore], @Ext=[Ext] van @tbl_files waar [DBName][email protected]; set @[email protected]+N' MOVE N'+N''''[email protected]+N''''+N' TO N'+N''''[email protected]+N' _Herstellen.'[email protected]+N''''+N','; verwijderen uit @tbl_files waar [DBName][email protected] en [SourcePathRestore][email protected] en [Ext][email protected]; eindset @[email protected]+N' NOUNLOAD, REPLACE, STATS =5'; exec(@sql); --controleren van de DB op integriteit set @sql=N'DBCC CHECKDB(N'+N''''[email protected]+'_Restore'+N''''+N') WITH NO_INFOMSGS'; exec(@sql); verwijderen uit @tbl waar [DBName][email protected]; eindeEND[/uitbreiden]
Om aan te geven welke volledige reservekopie moet worden gebruikt voor herstel, wordt een speciaal gestructureerde bestandsnaam gebruikt:
_Full_backup_ _ _ .bak Om dit databaseherstelproces te automatiseren, moet de aanroep van de opgeslagen procedure die we hebben geïmplementeerd in de Windows Taakplanner, Agent-taken of een vergelijkbare beschikbare service worden geplaatst.
U kunt de meest recente back-upkopieën van de database bekijken met de volgende weergave:
GEBRUIK [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 ' dan 'log' als 'I' dan 'differentieel' anders 'andere' einde, bs.[first_lsn], bs.[last_lsn], bs.[backup_start_date], bs.[backup_finish_date], cast(bs.[backup_size] als decimaal (18,3))/1024/1024 als BackupSizeMb, rownum =row_number() over ( partition by bs.[database_name], typ order by bs.[backup_finish_date] desc ), LogicalDeviceName =bmf.[logical_device_name], PhysicalDeviceName =bmf.[physical_device_name], bs.[server_name], bs.[user_name] VANAF msdb.dbo.backupset bs INNER WORDT Msdb.dbo.backupmediafamily bmf ON [bs].[media_set_id] =[bmf].[media_set_id]) selecteer [server_name] als [ServerName], [database_name] als [DBName], [user_name] als [USerName], [backup_type] als [BackupType], [backup_start_date] als [BackupStartDate], [backup_finish_date] als [BackupFinishDate], [BackupSizeMb], -- niet-gecomprimeerde grootte [LogicalDeviceName], [PhysicalDeviceName], [first_lsn] als [FirstLSN], [last_lsn] als [LastLSN]van backup_ctewhere rownum =1;Het resultaat
In deze handleiding hebben we gekeken naar een implementatie van een geautomatiseerd back-upproces op de ene server en het daaruit voortvloeiende herstel op een andere (bijvoorbeeld een testserver).
Met deze methode kunnen we het proces voor het maken van reservekopieën automatiseren, de reservekopieën controleren door ze te herstellen en de hierboven getoonde processen verfijnen.
Bronnen:
Back-up
Herstellen
Back-upset
CHECKDB
SHRINKFILE
sys.master_files