База с полной моделью восстановления (FULL).
Предположим, необходимо актуализировать тестовую базу.
Бэкап недельной давности, сегодня пятница, и с момента последнего бэкапа на диске накопилось около 80 файлов, а может быть и больше.
Делать полный бэкап базы ради актуализации тестовой базы - дело неоптимальное:
- времязатраты;
- заполнение дополнительного места на диске.
Поэтому нужно восстанавливать сразу из имеющихся файлов. И здесь снова нюанс: постоянное ручное указание множества файлов при восстановлении тоже приводит значительным трудозатратам.
Решение - скрипт, который сам читает каждый файл из определенного каталога и восстанавливает базу.
Ограничение: в скрипте необходимо указать имя базы, каталог со всеми архивами, логические имена файлов из бэкапа.
USE tempdb
DECLARE @DBNAME NVARCHAR(100) = 'Test1' --ЗАТИРАЕМАЯ БАЗА
DECLARE @DATANAME NVARCHAR(100) = 'test1'
DECLARE @LOGNAME NVARCHAR(100) = 'test1_log'
DECLARE @DIRPATH NVARCHAR(300) = 'F:\WEEK\test1'
declare @FullName nvarchar(300) = ''
declare @ERR NVARCHAR(4000) = ''
DECLARE @F TABLE
(
[FILENAME] NVARCHAR(255)
,DEPT INT
,[FILE] INT
)
INSERT INTO @F
exec xp_dirtree @DIRPATH,1,1
IF EXISTS(SELECT [TABLE_NAME] FROM [INFORMATION_SCHEMA].[TABLES] WHERE [TABLE_NAME] = 'ttemp')
BEGIN
DROP TABLE ttemp
END
SELECT
IDENTITY(INT, 1, 1) AS idstr
,T.*
INTO ttemp
FROM @F AS T
declare @spid int = 0
declare @i int = 0
declare @i2 int = 0
declare @cou int
declare @dinsql nvarchar(4000)
declare @fname nvarchar(300) = ''
declare @Recover nvarchar(12) = 'NORECOVERY'
DECLARE @DBPath NVARCHAR(300) = ''
DECLARE @LOGPath NVARCHAR(300) = ''
-- Full file paths
SET @dinsql = 'USE [' + @DBNAME + '] '
+ ' SET @DBPath = (SELECT TOP 1 UPPER(DF.physical_name) FROM sys.database_files AS DF WHERE UPPER(DF.type_desc) = ''ROWS'')'
EXEC sp_executesql @dinsql, N'@DBPath nvarchar(300) out', @DBPath = @DBPath OUT
SET @dinsql = 'USE [' + @DBNAME + '] '
+ ' SET @LOGPath = (SELECT TOP 1 UPPER(DF.physical_name) FROM sys.database_files AS DF WHERE UPPER(DF.type_desc) = ''LOG'')'
EXEC sp_executesql @dinsql, N'@LOGPath nvarchar(300) out', @LOGPath = @LOGPath OUT
--
--Closing all connections with db
select
IDENTITY(int, 1,1) as idstr,
t.text as txt,
s.*
into t1
from sys.sysprocesses s
cross apply sys.dm_exec_sql_text(s.sql_handle) t
where db_name(s.dbid) = @DBNAME
set @cou = (select COUNT(*) from t1)
while @i <= @cou
begin
set @i = @i + 1
set @spid = (select t.spid from t1 t where t.idstr = @i)
set @dinsql = 'kill ' + STR(@spid)
begin try
execute(@dinsql)
end try
begin catch
end catch
end
drop table t1
--
set @i = 0
set @cou = (select COUNT(*) from ttemp)
print 'cou=' + convert(nvarchar(10), @cou)
while @i <= @cou
begin
set @i = @i + 1
set @i2 = @i + 1
set @fname = (select t.[FILENAME] from ttemp t where t.idstr = @i)
IF NOT EXISTS(select t.[FILENAME] from ttemp t where t.idstr = @i2)
BEGIN
SET @Recover = 'RECOVERY'
END
set @FullName = @DIRPATH + '\' + @fname
IF @i < 2
BEGIN
set @dinsql = 'RESTORE DATABASE ['+@DBNAME+'] FROM DISK ='''+@FullName+''' WITH FILE = 1, MOVE N'''+@DATANAME+''' TO N'''+@DBPath+''', MOVE N'''+@LOGNAME+''' TO N'''+@LOGPath+''', ' + @Recover + ', NOUNLOAD, REPLACE, STATS = 5'
begin try
execute(@dinsql)
print @dinsql
end try
begin catch
SET @ERR = 'DBNAME: ' + @DBNAME
+'::Err №' + CONVERT(VARCHAR, ERROR_NUMBER())
+'; ErrorSeverity: '+ CAST(ERROR_SEVERITY() AS NVARCHAR(100))
+'; ErrorState: '+ CAST(ERROR_STATE() AS NVARCHAR(100))
+'; ErrorLine: '+ CONVERT(VARCHAR, ERROR_LINE())
+'; ErrorMessage: '+ ERROR_MESSAGE()
PRINT @ERR
break
end catch
CONTINUE
END
set @dinsql = 'RESTORE LOG ['+@DBNAME+'] FROM DISK ='''+@FullName+''' WITH FILE = 1, ' + @Recover
begin try
execute(@dinsql)
print @dinsql
end try
begin catch
SET @ERR = 'DBNAME: ' + @DBNAME
+'::Err №' + CONVERT(VARCHAR, ERROR_NUMBER())
+'; ErrorSeverity: '+ CAST(ERROR_SEVERITY() AS NVARCHAR(100))
+'; ErrorState: '+ CAST(ERROR_STATE() AS NVARCHAR(100))
+'; ErrorLine: '+ CONVERT(VARCHAR, ERROR_LINE())
+'; ErrorMessage: '+ ERROR_MESSAGE()
PRINT @ERR
break
end catch
end
DROP TABLE ttemp
Комментариев нет:
Отправить комментарий