Database
 sql >> база данни >  >> RDS >> Database

Внедряване на автоматизирано архивиране и възстановяване на база данни със средства по подразбиране

Въведение

Можете да намерите много ръководства как да архивирате и възстановявате бази данни. В този ще покажем как това може да стане с помощта на средствата по подразбиране на MS SQL Server.

Този пример ще обхване редица подходи – от проверка на целостта на базата данни преди нейното архивиране до възстановяване на базата данни от предварително създадено резервно копие.

Решението

Първо, нека разгледаме общия алгоритъм, който ще използваме за архивиране на база данни:

1) Определяне на кои бази данни трябва да бъдат архивирани
2) Проверка на целостта на избраните бази данни
3) Създаване на резервно копие (пълно, диференциално или копие на регистър на транзакциите) за всяка от избраните бази данни
4) Проверка на създадените резервни копия
5) Компресиране на регистрационните файлове на транзакциите (ако е необходимо)

По-долу можете да намерите пример за внедряване на този алгоритъм.

За да определим кои бази данни трябва да бъдат архивирани, ще създадем следната таблица:

ИЗПОЛЗВАЙТЕ [DB_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE TABLE [srv].[BackupSettings]( [DBID] [int] НЕ NULL, [FullPathBackup] [nvarchar](255) НЕ NULL, [DiffPathvarackup] [DiffPathvarackup](25) ) NULL, [LogPathBackup] [nvarchar](255) NULL, [InsertUTCDate] [datetime] NOT NULL, ОГРАНИЧЕНИЕ [PK_BackupSettings] ПЪРВИЧЕН КЛУСТЕР ( [DBID] ASC) WITH (PAD_INDEX =OFF, STATISTICS_NORECOM_NOTE, STATISTICS_NORECOM) ALLOW_ROW_LOCKS =ON, ALLOW_PAGE_LOCKS =ON) ON [PRIMARY]) ON [PRIMARY];GOALTER TABLE [srv].[BackupSettings] ДОБАВИ ОГРАНИЧЕНИЕ [DF_BackupSettings_InsertUTCDate] ПО ПОДРАЗБИРАНЕ (getutcdate [GOALTER](GOALTER)) 

Идентификаторът на базата данни се намира в първата колона, 'FullPathBackup' съдържа пътя за създаване на пълно архивно копие (например, 'disk:\…\'), а DiffPathBackup и LogPathBackup съдържат пълни пътища за създаване на диференциални копия и копия на регистрационните файлове на транзакциите съответно. Ако колоните DiffPathBackup или LogPathBackup са празни, тогава диференциалното и/или копието на регистрационния файл на транзакциите за тази база данни няма да бъде създадено.

Можем също да създадем представяне въз основа на тази таблица:

ИЗПОЛЗВАЙТЕ [DB_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE изглед [srv].[vBackupSettings]asSELECT [DBID] ,DB_Name([DBID]) като [DBName] ,[FullPathBackup] ,[Pa]DiffBacte[Da]Backup,[PathBackup] ] FROM [srv].[BackupSettings];GO

Това представяне ви позволява ефективно да проверите кои бази данни участват в процеса на архивиране.

Сега, нека създадем представяне, което показва информация за файла на базата данни от системното представяне sys.master_files:

ИЗПОЛЗВАЙТЕ [DB_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE изглед [inf].[ServerDBFileInfo] като SELECT @@Servername КАТО сървър , File_id ,--идентификатор на DB файл. Основната стойност за file_id е 1 Type_desc ,--Тип описание на файла Име като [FileName] ,--DB логическо име на файл LEFT(Physical_Name, 1) AS Drive ,--Флаг на устройството за местоположението на DB файла Physical_Name ,--Пълен файл име в OS RIGHT(physical_name, 3) AS Ext ,--Разширение на файла Размер като CountPage, --Текущ размер на файла в 8Kb страници кръг ((cast(Size*8 as float))/1024,3) като SizeMb, - -Размер на файла в Mb round((cast(Size*8 as float))/1024/1024,3) като SizeGb, --Размер на файла в Gb случай, когато is_percent_growth=0, след това Растеж*8, иначе 0 завършва като растеж, -- Увеличаване на файла в 8Kb страници, когато is_percent_growth=0, след това round((cast(Growth*8 as float))/1024,3) завършва като GrowthMb, --Растеж на файла в Mb случай, когато is_percent_growth=0, след това round((cast(Growth) *8 като float))/1024/1024,3) завършва като GrowthGb, --Растеж на файла в Gb случай, когато is_percent_growth=1, след това Растеж друго 0 завършва като GrowthPercent, --Растеж на файла в процент is_percent_growth, --Процент на растеж на атрибут database_id , DB_ Name(database_id) като [DB_Name], State,--Състояние на файла state_desc като StateDesc,--Описание на състоянието на файла is_media_read_only като IsMediaReadOnly,--Файлът се намира на устройството като само за четене (0 - и за запис) is_read_only като IsReadOnly ,--файлът е маркиран като само за четене (0 - и за запис) is_sparse като IsSpace,--Sparse файл is_name_reserved като IsNameReserved,--1 - Име на отдалечен файл, достъпно за използване. --Необходимо е да получите резервно копие на регистрационния файл, преди да използвате отново същото име (аргументи име или физическо_name) за нов файл --0 - Име на файл, недостъпно за използване create_lsn като CreateLsn,--Регистрационен номер на транзакцията в дневника (LSN) който беше използван за създаване на файла drop_lsn като DropLsn,--LSN, който беше използван за изтриване на файла read_only_lsn като ReadOnlyLsn,--LSN, който беше използван от файловата група, съдържаща файла, за промяна на типа "четене и запис" на "четене -only" (последната промяна) read_write_lsn като ReadWriteLsn,--LSN, който беше използван от файловата група, съдържаща файла, за промяна на типа "само за четене" на "read and write" (последната промяна) differential_base_lsn като DifferentialBaseLsn,- - База за диференциални резервни копия. Екстенти на данни, които са били променени, след като LSN е включен в диференциалното архивиране. differential_base_guid като DifferentialBaseGuid,--Уникален идентификатор на основното резервно копие, което ще се използва за създаване на диференциално копие. differential_base_time като DifferentialBaseTime,--Времето, съответстващо на differential_base_lsn redo_start_lsn като RedoStartLsn,--LSN, използвано за определяне на началото на следващото повторно изпълнение --Е NULL, с изключение на случаите, в които състояние =RESTORING или състояние =RECOVERY_start-PENDING за redko_gut -Уникален идентификатор за точката на разклона за възстановяване --стойността на аргумента first_fork_guid на следващото възстановено резервно копие трябва да е равна на тази стойност redo_target_lsn като RedoTargetLsn,--LSN, която служи като точка на спиране за повторение в "онлайн" режим в този файл -- Е NULL, с изключение на случаите, в които състояние =ВЪЗСТАНОВЯВАНЕ или състояние =RECOVERY_PENDING redo_target_fork_guid като RedoTargetForkGuid,--Разклонение за възстановяване, на което контейнерът може да бъде възстановен. Използва се заедно с redo_target_lsn backup_lsn като BackupLsn--LSN на най-новите данни или диференциалното архивно копие на файлаFROM sys.master_files--database_files;GO

За да създадете пълни резервни копия, нека приложим следната съхранена процедура:

[expand title =”Код “]

USE [DB_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOALTER ПРОЦЕДУРА [srv].[RunFullBackupDB] @ClearLog bit=1 --определя дали размерът на регистрационния файл на транзакциите трябва да бъде намаленASBEGIN /* Създаване на пълно архивно копие на DB и проверка на целостта на DB. предварително */ SET NOCOUNT ON; декларираме @dt datetime=getdate(); декларира @year int=YEAR(@dt); декларираме @month int=MONTH(@dt); декларираме @day int=DAY(@dt); декларираме @hour int=Част на датата(час, @dt); декларира @minute int=Част за дата(минута, @dt); декларира @second int=Част за дата(втора, @dt); декларира @pathBackup nvarchar(255); декларира @pathstr nvarchar(255); декларира @DBName nvarchar(255); декларираме @backupName nvarchar(255); декларира @sql nvarchar(max); декларира @backupSetId като int; декларира @FileNameLog nvarchar(255); declare @tbllog table( [DBName] [nvarchar](255) НЕ NULL, [FileNameLog] [nvarchar](255) NOT NULL ); декларира @tbl таблица ( [DBName] [nvarchar](255) НЕ NULL, [FullPathBackup] [nvarchar](255) NOT NULL); --Извличане на DB име и пълни пътища за създаване на пълно архивно копие, вмъкване в @tbl ( [DBName] ,[FullPathBackup] ) изберете DB_NAME([DBID]) ,[FullPathBackup] от [srv].[BackupSettings]; --Извличане на името на DB и имената на съответните регистрационни файлове на транзакциите (тъй като една DB може да има множество регистрационни файлове) вмъкнете в @tbllog([DBName], [FileNameLog]) изберете t.[DBName], tt.[FileName] като [FileNameLog] като [FileNameLog]). ] от @tbl като t вътрешно присъединяване [inf].[ServerDBFileInfo] като tt на t.[DBName]=DB_NAME(tt.[database_id]), където tt.[Type_desc]='LOG'; --последователно обработване на всяка от БД, които получихме по-рано while(exists(select top(1) 1 from @tbl)) begin set @backupSetId=NULL; изберете top(1) @DBName=[DBName], @pathBackup=[FullPathBackup] от @tbl; задайте @[email protected]+N'_Full_backup_'+cast(@година като nvarchar(255))+N'_'+cast(@месец като nvarchar(255))+N'_'+cast(@day като nvarchar(255))--+N'_' --+cast(@час като nvarchar(255))+N'_'+cast(@minute като nvarchar(255))+N'_'+cast(@ втори като nvarchar(255)); set @[email protected]@sqldat.com+N'.bak'; -- проверка на DB за целостта на набора @sql=N'DBCC CHECKDB(N'+N''''[email protected]+N''''+N') С NO_INFOMSGS'; exec(@sql); --изпълнение на процедурата за създаване на резервно копие set @sql=N'BACKUP DATABASE ['[email protected]+N'] НА ДИСК =N'+N''''[email protected]+N''''+ N' С NOFORMAT, NOINIT, NAME =N'+N''''[email protected]+N''''+ N', CHECKSUM, STOP_ON_ERROR, SKIP, PREWIND, COMPRESSION, STATS =10;'; exec(@sql); --проверка на създаденото от нас архивно копие изберете @backupSetId =позиция от msdb..backupset където [email protected] и backup_set_id=(изберете max(backup_set_id) от msdb..backupset, където [email protected]); set @sql=N'Грешка при проверка. Информацията за архивно копие за база данни "'[email protected]+'" не е намерена.'; ако @backupSetId е null begin raiserror(@sql, 16, 1) end else begin set @sql=N'RESTORE VERIFYONLY FROM DISK =N'+''''[email protected]+N''''+N' С ФАЙЛ ='+cast(@backupSetId като nvarchar(255)); exec(@sql); край -- компресиране на регистрите на транзакциите на DB if(@ClearLog=1) започва докато (съществува(изберете отгоре(1) 1 от @tbllog където [DBName][email protected])) начало изберете top(1) @FileNameLog=FileNameLog от @tbllog, където [email protected]; set @sql=N'USE ['[email protected]+N'];'+N' DBCC SHRINKFILE (N'+N''''[email protected]+N''''+N' , 0 , САМО ОСЪЩАНЕ)'; exec(@sql); изтрийте от @tbllog, където [email protected] и [email protected]; край край изтриване от @tbl където [DBName][email protected]; крайENDGO

[/expand]

Според кода можем да видим, че тази процедура предоставя решение за останалите стъпки от алгоритъма за създаване на резервно копие.

Процедурите, които създават копия на диференциални и транзакционни регистрационни файлове, се изпълняват по подобен начин:

[expand title =”Код “]

USE [DB_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOALTER ПРОЦЕДУРА [srv].[RunDiffBackupDB] @ClearLog bit=1 --определя дали размерът на регистрационния файл на транзакциите трябва да бъде намаленASBEGIN /* Създаване на диференциално резервно копие на DB COUNT */ SET NO; декларираме @dt datetime=getdate(); декларира @year int=YEAR(@dt); декларираме @month int=MONTH(@dt); декларираме @day int=DAY(@dt); декларираме @hour int=Част на датата(час, @dt); декларира @minute int=Част за дата(минута, @dt); декларира @second int=Част за дата(втора, @dt); декларира @pathBackup nvarchar(255); декларира @pathstr nvarchar(255); декларира @DBName nvarchar(255); декларираме @backupName nvarchar(255); декларира @sql nvarchar(max); декларира @backupSetId като int; декларира @FileNameLog nvarchar(255); декларира @tbl таблица ( [DBName] [nvarchar](255) НЕ НУЛЕВО, [DiffPathBackup] [nvarchar](255) NOT NULL ); declare @tbllog table( [DBName] [nvarchar](255) НЕ NULL, [FileNameLog] [nvarchar](255) NOT NULL ); --Извличане на името на DB и пълните пътища за създаване на диференциални резервни копия, вмъкване в @tbl ( [DBName] , [DiffPathBackup] ) изберете DB_NAME([DBID]) , [DiffPathBackup] от [srv].[BackupSettings], където [DiffPathBackup] не е нула; --Извличане на DB име и пълните имена на съответните регистрационни файлове на транзакциите (тъй като една DB може да има множество регистрационни файлове) вмъкнете в @tbllog([DBName], [FileNameLog]) изберете t.[DBName], tt.[FileName] като име на файл. [FileNameLog] от @tbl като t вътрешно присъединяване [inf].[ServerDBFileInfo] като tt на t.[DBName]=DB_NAME(tt.[database_id]), където tt.[Type_desc]='LOG'; --последователно обработване на всяка от БД, които получихме по-рано while(exists(select top(1) 1 from @tbl)) begin set @backupSetId=NULL; изберете top(1) @DBName=[DBName], @pathBackup=[DiffPathBackup] от @tbl; задайте @[email protected]+N'_Diff_backup_'+cast(@година като nvarchar(255))+N'_'+cast(@месец като nvarchar(255))+N'_'+cast(@day като nvarchar(255))+N'_' +cast(@час като nvarchar(255))+N'_'+cast(@minute като nvarchar(255))+N'_'+cast(@second като nvarchar( 255)); set @[email protected]@sqldat.com+N'.bak'; -- проверка на DB за целостта на набора @sql=N'DBCC CHECKDB(N'+N''''[email protected]+N''''+N') С NO_INFOMSGS'; exec(@sql); --изпълнение на процедурата за архивиране set @sql=N'BACKUP DATABASE ['[email protected]+N'] НА ДИСК =N'+N''''[email protected]+N''''+ N' С ДИФЕРЕНЦИАЛ, NOFORMAT, NOINIT, NAME =N'+N''''[email protected]+N''''+ N', CHECKSUM, STOP_ON_ERROR, SKIP, REWIND, COMPRESSION, STATS =10;'; exec(@sql); --проверка на резервното копие, което току-що създадохме, изберете @backupSetId =позиция от msdb..backupset където [email protected] и backup_set_id=(изберете max(backup_set_id) от msdb..backupset където [email protected]); set @sql=N'Грешка при проверка. Информацията за архивно копие за база данни "'[email protected]+'" не е намерена.'; ако @backupSetId е null begin raiserror(@sql, 16, 1) end else begin set @sql=N'RESTORE VERIFYONLY FROM DISK =N'+''''[email protected]+N''''+N' С ФАЙЛ ='+cast(@backupSetId като nvarchar(255)); exec(@sql); край -- компресиране на регистрите на транзакциите на DB if(@ClearLog=1) започва докато (съществува(изберете отгоре(1) 1 от @tbllog където [DBName][email protected])) начало изберете top(1) @FileNameLog=FileNameLog от @tbllog, където [email protected]; set @sql=N'USE ['[email protected]+N'];'+N' DBCC SHRINKFILE (N'+N''''[email protected]+N''''+N' , 0 , САМО ОСЪЩАНЕ)'; exec(@sql); изтрийте от @tbllog, където [email protected] и [email protected]; край край изтриване от @tbl където [DBName][email protected]; крайENDGO

[/expand]

Тъй като проверката на бази данни за целостта отнема много ресурси, можем да я пропуснем, докато създаваме диференциално резервно копие.

[expand title =”Код “]

ИЗПОЛЗВАЙТЕ [DB_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOALTER ПРОЦЕДУРА [srv].[RunLogBackupDB] @ClearLog bit=1 --определя дали размерът на регистрационния файл на транзакциите трябва да бъде намаленASBEGIN /* Архивиране на дневника на транзакциите на DB */ SET NOCOUNT NO декларираме @dt datetime=getdate(); декларира @year int=YEAR(@dt); декларираме @month int=MONTH(@dt); декларираме @day int=DAY(@dt); декларираме @hour int=Част на датата(час, @dt); декларира @minute int=Част за дата(минута, @dt); декларира @second int=Част за дата(втора, @dt); декларира @pathBackup nvarchar(255); декларира @pathstr nvarchar(255); декларира @DBName nvarchar(255); декларираме @backupName nvarchar(255); декларира @sql nvarchar(max); декларира @backupSetId като int; декларира @FileNameLog nvarchar(255); декларира @tbl таблица ( [DBName] [nvarchar](255) НЕ NULL, [LogPathBackup] [nvarchar](255) NOT NULL ); declare @tbllog table( [DBName] [nvarchar](255) НЕ NULL, [FileNameLog] [nvarchar](255) NOT NULL ); --Извличане на имена на DB и пълни пътища за създаване на резервни копия на регистрационни файлове на транзакции с непрост модел за възстановяване (пълен или групово регистриран). Системните DB също са изключени, вмъкнете в @tbl ( [DBName] ,[LogPathBackup] ) изберете DB_NAME(b.[DBID]) ,b.[LogPathBackup] от [srv].[BackupSettings] като b вътрешно присъединяване sys.databases като d d. на b.[DBID]=d.[database_id], където d.recovery_model<3 и DB_NAME([DBID]) не са в ( N'master', N'tempdb', N'model', N'msdb', N' ReportServer', N'ReportServerTempDB' ) и [LogPathBackup] не е нула; --Извличане на DB име и пълните имена на съответните регистрационни файлове на транзакциите (тъй като една DB може да има множество регистрационни файлове) вмъкнете в @tbllog([DBName], [FileNameLog]) изберете t.[DBName], tt.[FileName] като име на файл. [FileNameLog] от @tbl като t вътрешно присъединяване [inf].[ServerDBFileInfo] като tt на t.[DBName]=DB_NAME(tt.[database_id]), където tt.[Type_desc]='LOG'; --последователно обработване на всяка от БД, които получихме по-рано while(exists(select top(1) 1 from @tbl)) begin set @backupSetId=NULL; изберете top(1) @DBName=[DBName], @pathBackup=[LogPathBackup] от @tbl; задайте @[email protected]+N'_Log_backup_'+cast(@година като nvarchar(255))+N'_'+cast(@месец като nvarchar(255))+N'_'+cast(@day като nvarchar(255))+N'_' +cast(@час като nvarchar(255))+N'_'+cast(@minute като nvarchar(255))+N'_'+cast(@second като nvarchar( 255)); set @[email protected]@sqldat.com+N'.trn'; --изпълнение на процедурата за архивиране set @sql=N'BACKUP LOG ['[email protected]+N'] НА ДИСК =N'+N''''[email protected]+N''''+ N' С NOFORMAT, NOINIT, NAME =N'+N''''[email protected]+N''''+ N', CHECKSUM, STOP_ON_ERROR, SKIP, НАЗАД, КОМПРЕСИЯ, СТАТИСТИКА =10;'; exec(@sql); --Проверка на резервното копие на дневника на транзакциите, което току-що създадохме, изберете @backupSetId =позиция от msdb..backupset, където [email protected] и backup_set_id=(изберете max(backup_set_id) от msdb..backupset където [email protected]); set @sql=N'Грешка при проверка. Информацията за архивно копие за база данни "'[email protected]+'" не е намерена.'; ако @backupSetId е null begin raiserror(@sql, 16, 1) end else begin set @sql=N'RESTORE VERIFYONLY FROM DISK =N'+''''[email protected]+N''''+N' С ФАЙЛ ='+cast(@backupSetId като nvarchar(255)); exec(@sql); край -- компресиране на регистрите на транзакциите на DB if(@ClearLog=1) започва докато (съществува(изберете отгоре(1) 1 от @tbllog където [DBName][email protected])) начало изберете top(1) @FileNameLog=FileNameLog от @tbllog, където [email protected]; set @sql=N'USE ['[email protected]+N'];'+N' DBCC SHRINKFILE (N'+N''''[email protected]+N''''+N' , 0 , САМО ОТСЪЩАНЕ)'; exec(@sql); изтрийте от @tbllog, където [email protected] и [email protected]; край край изтриване от @tbl където [DBName][email protected]; крайENDGO

[/expand]

Както беше казано по-горе, проверката на базите данни за интегритет е задача, която изисква много ресурси. В комбинация с факта, че резервните копия на регистрационните файлове на транзакциите обикновено трябва да се създават доста често, това ни дава причина да пропуснем проверката на целостта, докато създаваме копие на регистрационния файл на транзакциите.

Моля, имайте предвид също, че периодично трябва да се правят пълни резервни копия на бази данни „основни“, „msdb“ и „model“.

За да автоматизирате процеса на създаване на резервно копие, просто ще трябва да извикате вече внедрените процедури в Windows Task Scheduler, задачи на агенти или друга подобна налична услуга.

Ще трябва да зададете честотата на повикванията за всяка от тези процедури поотделно въз основа на пикове на натоварване, плато на активност и т.н.

Основният подход е следният:

1) Създаване на пълно архивно копие веднъж на ден
2) Създаване на диференциални резервни копия на всеки 2-4 часа
3) Създаване на резервни копия на регистрационните файлове на транзакциите на всеки 5-60 минути

Моля, имайте предвид, че обикновено базите данни участват в системата за безопасен и бърз достъп. И ако последният използва резервни копия на регистрационните файлове на транзакциите, жизненоважно е да не се намесва в процедурата. По-конкретно, това означава, че копията на регистрационните файлове на транзакциите не трябва да се създават от няколко различни процеса – ако това се случи, резервната последователност от тези копия ще бъде загубена.

Тук сме виждали примери за всяка база данни, която се обработва последователно, една по една. Въпреки това можем да постигнем паралелна обработка в производствена среда – позволявайки едновременно да се правят няколко резервни копия. Към това може да се подходи по няколко различни начина. Например, като извикате следната съхранена процедура:

ИЗПОЛЗВАЙТЕ [DB_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE PROCEDURE [inf].[RunAsyncExecute]( @sql nvarchar(max), @jobname nvarchar(57) =null, @database nvar(@nu1ll2,nvar) 128) =null)AS BEGIN/* Асинхронно изпълнение на пакета чрез задачите на агента RunAsyncExecute - асинхронно изпълнение на T-SQL команда или съхранено prodecure 2012 Antonin Foller, Motobit Software, www.motobit.com http://www.motobit.com/ tips/detpg_async-execute-sql/ */ SET NOCOUNT ON; декларира @id uniqueidentifier; --Създаване на уникално име на задание, ако името не е посочено, ако (@име на работа е нула) зададете @име на задача=''; set @jobname =@jobname + '_async_' + convert(varchar(64),NEWID()); if (@owner е null) set @owner ='sa'; --Създайте нова работа, вземете идентификатор на заданието, изпълнете msdb..sp_add_job @ime на задача, @[email protected], @[email protected] ИЗХОД; --Посочете сървър на задания за изпълнение на заданието msdb..sp_add_jobserver @[email protected]; --Посочете първа стъпка от заданието - SQL командата ---(@on_success_action =3 ... Преминете към следващата стъпка) изпълнете msdb..sp_add_jobstep @[email protected], @step_name='Step1', @command =@sql, @database_name =@database, @on_success_action =3; --Посочете следващата стъпка от заданието - изтрийте заданието declare @deletecommand varchar(200); set @deletecommand ='изпълни msdb..sp_delete_job @job_name='''[email protected]+''''; изпълнете msdb..sp_add_jobstep @[email protected], @step_name='Step2', @command =@deletecommand; --Стартирайте заданието, изпълнявайте msdb..sp_start_job @[email protected]; END GO

Тук асинхронността се постига чрез динамично създаване на заданията на агента, изпълнението и изтриването им след това.

Сега, нека разгледаме общия алгоритъм за възстановяване на бази данни от резервни копия, създадени преди това в различна/тестова среда:

1) Определяне кои бази данни трябва да бъдат възстановени и местоположението на техните резервни копия
2) Възстановяване на базите данни
3) Проверка на възстановените бази данни за целостта

Сега ще разгледаме реализация на алгоритъм, който възстановява база данни от пълно архивно копие. За диференциално копие процедурата е подобна – единствената разлика е, че пълното резервно копие трябва да бъде възстановено от първа ръка, последвано от диференциалното копие.

За да определим кои бази данни трябва да бъдат възстановени, както и местоположението на техните резервни копия, нека създадем две таблици, както е показано по-долу:

ИЗПОЛЗВАЙТЕ [DB_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE TABLE [srv].[RestoreSettings]( [DBName] [nvarchar](255) НЕ NULL, [FullPathRestore] [nvarchar](255) [nvarchar](255) N. ](255) NOT NULL, [LogPathRestore] [nvarchar](255) NOT NULL, [InsertUTCDate] [datetime] NOT NULL, ОГРАНИЧЕНИЕ [PK_RestoreSettings] ПЪРВИЧЕН КЛУСТЕР ( [DBName] ASC)WITH =(PAD_IND_INDEX.COM) , IGNORE_DUP_KEY =ИЗКЛЮЧЕНО, ALLOW_ROW_LOCKS =ON, ALLOW_PAGE_LOCKS =ON) ON [PRIMARY]) ON [PRIMARY];GOALTER TABLE [srv].[RestoreSettings] ДОБАВЯНЕ НА ОГРАНИЧЕНИЕ [DF_RestoreSettingste]DEFAULT (GOALTERSETTSTE)DEFAULT (GOALTERSETTSTE) /предварително> 

Тук предназначението на колоните е аналогично на тези от таблицата [srv].[BackupSettings]. Единствената разлика е, че пълният път ще се използва за намиране на резервни копия за възстановяване, а не за създаване на нови.

ИЗПОЛЗВАЙТЕ [DB_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE TABLE [srv].[RestoreSettingsDetail]( [Row_GUID] [uniqueidentifier] NOT NULL, [DBName] [nvarchar](255) [SourcePanth] [SourcePanth55] [SourcePanth55] ) NOT NULL, TargetPathRestore [nvarchar](255) NOT NULL, [Ext] [nvarchar](255) NOT NULL, [InsertUTCDate] [datetime] NOT NULL, CONSTRAINT [PK_RestoreSettingsDetail] PRIMARY ARESCow_CLUSTEREDWID ( 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]. FOR [Row_GUID];GOALTER TABLE [srv].[RestoreSettingsDetail] ДОБАВЯНЕ НА ОГРАНИЧЕНИЕ [DF_RestoreSettingsDetail_InsertUTCDate] ПО ПРАВО (getutcdate()) ЗА [InsertUTCDate];GO

Тази таблица е необходима, за да се дефинират пълните имена на файлове на базата данни, която се възстановява, които след това се използват за по-нататъшно прехвърляне (например, [SourcePathRestore]='Име на логически файл' и [TargetPathRestore]='disk:\…\Physical file name ', докато [Ext]='Разширение на файла')

Всъщност можем да дефинираме логически имена на файловете на базата данни, като използваме следната заявка:

ВЪЗСТАНОВЯВАНЕ НА FILELISTONLY ОТ ДИСК ='disk:\...\backup copy.BAK';

Получаването на информация за резервни копия, намиращи се във файл, може да стане по следния начин:

RESTORE HEADERONLYFROM DISK='disk:\...\backup copy.BAK';

След това имаме изпълнение на съхранена процедура, използвана за възстановяване на база данни от пълно архивно копие и проверка за целостта на данните:

[expand title =”Код “]

ИЗПОЛЗВАЙТЕ [DB_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOALTER PROCEDURE [srv].[RunFullRestoreDB]ASBEGIN /* Възстановяване на DB от пълно архивно копие и проверка на DB за целостта */ SET NOCOUNT ON; декларира @dt datetime=DateAdd(day,-2,getdate()); декларира @year int=YEAR(@dt); декларираме @month int=MONTH(@dt); декларираме @day int=DAY(@dt); декларираме @hour int=Част на датата(час, @dt); декларира @minute int=Част за дата(минута, @dt); декларира @second int=Част за дата(втора, @dt); декларира @pathBackup nvarchar(255); декларира @pathstr nvarchar(255); декларира @DBName nvarchar(255); декларираме @backupName nvarchar(255); декларира @sql nvarchar(max); декларира @backupSetId като int; декларира @FileNameLog nvarchar(255); декларира @SourcePathRestore nvarchar(255); декларира @TargetPathRestore nvarchar(255); декларира @Ext nvarchar(255); декларира @tbl таблица ( [DBName] [nvarchar](255) НЕ NULL, [FullPathRestore] [nvarchar](255) NOT NULL); декларира таблица @tbl_files ( [DBName] [nvarchar](255) НЕ NULL, [SourcePathRestore] [nvarchar](255) NOT NULL, [TargetPathRestore] [nvarchar](255) NOT NULL, [Ext] [nvarchar](25) НЕ НУЛЕВО); --извличане на списък с имена на DB и пътищата към пълните архивни копия, вмъкване в @tbl ( [DBName] ,[FullPathRestore] ) изберете [DBName] ,[FullPathRestore] от [srv].[RestoreSettings]; --извличане на подробна информация за новото местоположение на DB файлове, вмъкване в @tbl_files ( [DBName] ,[SourcePathRestore] ,[TargetPathRestore] ,[Ext] ) изберете [DBName] ,[SourcePathRestore] ,[TargetPathRestore] от [Ext srv].[RestoreSettingsDetail]; --обработване на всяка от БД, които получихме по-рано while(exists(select top(1) 1 from @tbl)) begin set @backupSetId=NULL; изберете top(1) @DBName=[DBName], @pathBackup=[FullPathRestore] от @tbl; задайте @[email protected]+N'_Full_backup_'+cast(@година като nvarchar(255))+N'_'+cast(@месец като nvarchar(255))+N'_'+cast(@day като nvarchar(255))--+N'_' --+cast(@час като nvarchar(255))+N'_'+cast(@minute като nvarchar(255))+N'_'+cast(@ втори като nvarchar(255)); set @[email protected]@sqldat.com+N'.bak'; --създаване на резервна заявка и изпълнението й set @sql=N'RESTORE DATABASE ['[email protected]+N'_Restore] ОТ ДИСКА =N'+N''''[email protected]+N''' '+ N' С ФАЙЛ =1,'; while(exists(select top(1) 1 from @tbl_files where [DBName][email protected])) start select top(1) @SourcePathRestore=[SourcePathRestore], @TargetPathRestore=[TargetPathRestore], @Ext=[Ext] от @tbl_files, където [DBName][email protected]; set @[email protected]+N' MOVE N'+N''''[email protected]+N''''+N' TO N'+N''''[email protected]+N' _Възстановяване.'[email protected]+N''''+N','; изтрийте от @tbl_files, където [DBName][email protected] и [SourcePathRestore][email protected] и [Ext][email protected]; крайно множество @[email protected]+N' NOUNLOAD, REPLACE, STATS =5'; exec(@sql); --проверка на DB за целитет набор @sql=N'DBCC CHECKDB(N'+N''''[email protected]+'_Restore'+N''''+N') С NO_INFOMSGS'; exec(@sql); изтрийте от @tbl, където [DBName][email protected]; крайEND

[/expand]

За да посочите кое пълно резервно копие да се използва за възстановяване, се използва специално структурирано име на файла:

_Full_backup_<година>__.bak

За да се автоматизира този процес на възстановяване на база данни, извикването на съхранената процедура, която внедрихме, трябва да бъде поставено в Windows Task Scheduler, задания на агенти или друга подобна налична услуга.

Можете да видите най-новите архивни копия на базата данни, като използвате следното представяне:

ИЗПОЛЗВАЙТЕ [DB_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE VIEW [inf].[vServerLastBackupDB] като backup_cte as( изберете bs.[database_name], backup_type =case bs.[type], когато 'D', тогава ', когато 'D', когато ' ' след това 'log', когато 'I', след това 'диференциално' друго 'other' край, bs.[first_lsn], bs.[last_lsn], bs.[backup_start_date], bs.[backup_finish_date], cast(bs.[backup_size] като decimal(18,3))/1024/1024 като BackupSizeMb, rownum =row_number() над ( дял по bs.[име_база_на_данни], тип ред по bs.[backup_finish_date] desc), LogicalDeviceName =bmf.[logical_device_name], Na Physical_device. =bmf.[име_на_физическо_устройство], bs.[име_на_сървър], bs.[име_на_потребител] ОТ msdb.dbo.backupset bs ВЪТРЕШНО ПРИСЪЕДИНЯВАНЕ msdb.dbo.backupmediafamily bmf ON [bs].[media_set_id] =[bmf].[media_set_id]). изберете [име_сървър] като [ServerName], [database_name] като [DBName], [user_name] като [UserName], [backup_type] като [BackupType], [backup_start_date] като [BackupStartDate], [backup_finish_date] като [BackupFinishDate], [BackupFinishDate --Mb], некомпресиран размер [LogicalDeviceName], [PhysicalDeviceName], [first_lsn] като [FirstLSN], [last_lsn] като [LastLSN]от backup_cte, където rownum =1;

Резултатът

В това ръководство разгледахме реализация на автоматизиран процес на архивиране на един сървър и последващо възстановяване на друг (например тестов сървър).

Този метод ни позволява да автоматизираме процеса на създаване на резервни копия, да проверяваме резервните копия, като ги възстановяваме и фино настройваме процесите, показани по-горе.

Източници:

Архив
Възстановяване
Набор от архивни копия
CHECKDB
SHRINKFILE
sys.master_files


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Съхранена процедура за получаване на информация за таблици на базата данни

  2. Внедряване на приложение Django в AWS Elastic Beanstalk

  3. Как да създадете изглед в SQL

  4. Още онлайн операции са налични сега или скоро

  5. Как да изтриете ограничение за външен ключ в SQL