Bir Klasördeki Tüm Backup Dosyalarını Restore Etmek / Restore All Backup Files

Merhaba;

Bu yazımda işinize yarayacağını düşündüğüm bir script paylaşmak istiyorum sizinle.

Çoğumuz belli bir serverda bulunan veritabanlarını başka bir servera taşıma ve kopyalama ihtiyacı duymuşuzdur. Ama sayı olarak çok fazla DB olduğunda bu işlem biraz yorucu ve sıkıcı olabilir 🙂

Bunun için bir SP yazdım.
Bu sp ile parametre olarak olarak belirttiğiniz klasördeki tüm .bak dosyalarının içini okuyup databaseleri servera restore edebilirsiniz. Ayrıca eğer varsa full text search dosyalarınıda restore edecektir.
Create scriptini aşağıda bulabilirsiniz. SPyi master db veya DBA scriptlerinizin olduğu veritabanında çalıştırabilirsiniz.

SPnin kullanımı şu şekilde;

EXEC sp_RestoreAllBackupFiles
		 @BackupPath = 'C:\Backup'
		,@DataPath = NULL
		,@LogPath = NULL
		,@Replace = 0
		,@Recovery = 1
		,@Execute = 0


Parametrelerin açıklaması;

Parametre

Açıklama

Default Değer

@BackupPath

.bak dosyalarının bulunduğu path bilgisi.

@DataPath

Data (.MDF, .NDF) dosyalarının restore edileceği yer. NULL olursa orjinal lokasyonlarına restore eder.

NULL

@LogPath

Log (.LDF) dosyasının restore edileceği yer. NULL olursa orjinal lokasyonuna restore eder.

NULL

@Replace

1: Aynı isimdeki mevcut veritabanı ile değiştirir.

0: Mevcut veritabanı ile değiştirmez, varsa hata verir.

0

@Recovery

1: Restore with recovery

0: Restore with norecovery

1

@Execute

1: İşlemi hemen yapar.

0: Sadece script üretir.

0

CREATE PROC sp_RestoreAllBackupFiles

@BackupPath VARCHAR(256),
@DataPath VARCHAR(256) = NULL,
@LogPath VARCHAR(256) = NULL,
@Replace BIT = 0,
@Recovery BIT = 1,
@Execute BIT = 0

AS

SET NOCOUNT ON

DECLARE @DBList TABLE (rowid INT NOT NULL IDENTITY(1, 1), NAME VARCHAR(500))
DECLARE @backupFilesPath VARCHAR(256)
DECLARE @cmd VARCHAR(max)
DECLARE @Ncmd NVARCHAR(4000)
DECLARE @dataFilesPath VARCHAR(256)
DECLARE @logFilesPath VARCHAR(256)
DECLARE @dbname VARCHAR(500)
DECLARE @LogicalName VARCHAR(256)
DECLARE @PhysicalName VARCHAR(256)
DECLARE @LogicalName_log VARCHAR(256)
DECLARE @PhysicalName_log VARCHAR(256)
DECLARE @fileName VARCHAR(256)
DECLARE @counter INT
DECLARE @startid INT = 1
DECLARE @charIndex INT
DECLARE @MDF VARCHAR(256)
DECLARE @NDF VARCHAR(256)
DECLARE @LDF VARCHAR(256)
DECLARE @replaceDB BIT
DECLARE @recoveryDB BIT
DECLARE @dataFiles TABLE (rowid INT, fileid INT, physicalname VARCHAR(256))
DECLARE @count INT
DECLARE @ndfCmd VARCHAR(2000) = ''
DECLARE @exec BIT
DECLARE @cmdshell TABLE (name nvarchar(200),minumum int,maximum int,config_value int, run_value int)
DECLARE @isDataPathNull BIT
DECLARE @isLogPathNull BIT

------------------------------------
SET @backupFilesPath = @BackupPath
SET @dataFilesPath = @DataPath
SET @logFilesPath = @LogPath
SET @replaceDB = @Replace
SET @recoveryDB = @Recovery
SET @exec = @Execute
------------------------------------

SET @startid = 1
SET @ndfCmd = ''

IF (@dataFilesPath IS NOT NULL)
BEGIN
SET @isDataPathNull = 0
IF((SELECT RIGHT(@dataFilesPath,1)) = '\')
SET @dataFilesPath = LEFT(@dataFilesPath,LEN(@dataFilesPath)-1)
END
ELSE
SET @isDataPathNull = 1

IF (@logFilesPath IS NOT NULL)
BEGIN
SET @isLogPathNull = 0
IF((SELECT RIGHT(@logFilesPath,1)) = '\')
SET @logFilesPath = LEFT(@logFilesPath,LEN(@logFilesPath)-1)
END
ELSE
SET @isLogPathNull = 1

IF EXISTS (SELECT name FROM tempdb.sys.tables WHERE name = '##headerTable')
 DROP TABLE ##headerTable

IF EXISTS (SELECT name FROM tempdb.sys.tables WHERE name = '##fileListTable')
 DROP TABLE ##fileListTable

CREATE TABLE ##headerTable (
 [BackupName] NVARCHAR(128),
 [BackupDescription] NVARCHAR(255),
 [BackupType] SMALLINT,
 [ExpirationDate] DATETIME,
 [Compressed] TINYINT,
 [Position] SMALLINT,
 [DeviceType] TINYINT,
 [UserName] NVARCHAR(128),
 [ServerName] NVARCHAR(128),
 [DatabaseName] NVARCHAR(128),
 [DatabaseVersion] INT,
 [DatabaseCreationDate] DATETIME,
 [BackupSize] NUMERIC(20,0),
 [FirstLSN] NUMERIC(25,0),
 [LastLSN] NUMERIC(25,0),
 [CheckpointLSN] NUMERIC(25,0),
 [DatabaseBackupLSN] NUMERIC(25,0),
 [BackupStartDate] DATETIME,
 [BackupFinishDate] DATETIME,
 [SortOrder] SMALLINT,
 [CodePage] SMALLINT,
 [UnicodeLocaleId] INT,
 [UnicodeComparisonStyle] INT,
 [CompatibilityLevel] TINYINT,
 [SoftwareVendorId] INT,
 [SoftwareVersionMajor] INT,
 [SoftwareVersionMinor] INT,
 [SoftwareVersionBuild] INT,
 [MachineName] NVARCHAR(128),
 [Flags] INT,
 [BindingID] UNIQUEIDENTIFIER,
 [RecoveryForkID] UNIQUEIDENTIFIER,
 [Collation] NVARCHAR(128),
 [FamilyGUID] UNIQUEIDENTIFIER,
 [HasBulkLoggedData] BIT,
 [IsSnapshot] BIT,
 [IsReadOnly] BIT,
 [IsSingleUser] BIT,
 [HasBackupChecksums] BIT,
 [IsDamaged] BIT,
 [BeginsLogChain] BIT,
 [HasIncompleteMetaData] BIT,
 [IsForceOffline] BIT,
 [IsCopyOnly] BIT,
 [FirstRecoveryForkID] UNIQUEIDENTIFIER,
 [ForkPointLSN] NUMERIC(25,0),
 [RecoveryModel] NVARCHAR(60),
 [DifferentialBaseLSN] NUMERIC(25,0),
 [DifferentialBaseGUID] UNIQUEIDENTIFIER,
 [BackupTypeDescription] NVARCHAR(60),
 [BackupSetGUID] UNIQUEIDENTIFIER,
 [CompressedBackupSize] BIT --,
 --[containment] TINYINT
 )

IF ((SELECT SUBSTRING(CAST(SERVERPROPERTY('productversion') AS NVARCHAR),1, (CHARINDEX('.',CAST(SERVERPROPERTY('productversion') AS NVARCHAR))-1))) > 10)
BEGIN
 ALTER TABLE ##headerTable ADD [containment] TINYINT NULL
END
CREATE TABLE ##fileListTable (
 [LogicalName] NVARCHAR(128),
 [PhysicalName] NVARCHAR(260),
 [Type] CHAR(1),
 [FileGroupName] NVARCHAR(128),
 [Size] NUMERIC(20,0),
 [MaxSize] NUMERIC(20,0),
 [FileID] BIGINT,
 [CreateLSN] NUMERIC(25,0),
 [DropLSN] NUMERIC(25,0),
 [UniqueID] UNIQUEIDENTIFIER,
 [ReadOnlyLSN] NUMERIC(25,0),
 [ReadWriteLSN] NUMERIC(25,0),
 [BackupSizeInBytes] BIGINT,
 [SourceBlockSize] INT,
 [FileGroupID] INT,
 [LogGroupGUID] UNIQUEIDENTIFIER,
 [DifferentialBaseLSN] NUMERIC(25,0),
 [DifferentialBaseGUID] UNIQUEIDENTIFIER,
 [IsReadOnly] BIT,
 [IsPresent] BIT,
 [TDEThumbprint] VARBINARY(32)
 )

IF((SELECT RIGHT(@backupFilesPath,1)) = '\')
SET @backupFilesPath = LEFT(@backupFilesPath,LEN(@backupFilesPath)-1)

SET @cmd = 'DIR ' + @backupFilesPath + '\*.bak /B'
SET @Ncmd = @cmd

IF((SELECT value FROM sys.configurations WHERE name = 'xp_cmdshell') = 0)
BEGIN
 --Enable xp_cmdshell
 EXEC sp_configure 'show advanced options', 1
 RECONFIGURE
 EXEC sp_configure 'xp_cmdshell', 1
 RECONFIGURE

INSERT INTO @DBList
 EXEC xp_cmdshell @Ncmd

--Disable xp_cmdshell
 EXEC sp_configure 'show advanced options', 1
 RECONFIGURE
 EXEC sp_configure 'xp_cmdshell', 0
 RECONFIGURE
END
ELSE
BEGIN
 INSERT INTO @DBList (name)
 EXEC xp_cmdshell @Ncmd
END

DELETE
FROM @DBList
WHERE NAME IS NULL
 OR NAME NOT LIKE '%.bak'

IF((SELECT COUNT(*) from @DBList) = 0)
BEGIN
GOTO ExitCode
END

SET @cmd = ''

SELECT @counter = count(NAME)
FROM @DBList

WHILE (@startid <= @counter)
BEGIN
 SELECT @fileName = NAME
 FROM @DBList
 WHERE rowid = @startid

 DELETE
 FROM ##headerTable
 INSERT INTO ##headerTable
 EXEC ('RESTORE HEADERONLY FROM disk=''' + @backupFilesPath + '\' + @filename + '''')

 IF ((SELECT [DatabaseName] FROM ##headerTable) IN ('master', 'model', 'msdb', 'tempdb', 'distribution'))
 GOTO ContinueLoop;

 DELETE
 FROM ##fileListTable
 INSERT INTO ##fileListTable
 EXEC ('RESTORE FILELISTONLY FROM disk=''' + @backupFilesPath + '\' + @filename + '''')

SELECT @MDF = physicalname
 FROM ##fileListTable
 WHERE TYPE = 'D'
 AND fileid = 1

SET @MDF = REVERSE(@MDF)
 SET @charIndex = charindex('\', @MDF)
 SET @MDF = LEFT(@MDF, @charIndex - 1)
 SET @MDF = REVERSE(@MDF)

SELECT @LDF = physicalname
 FROM ##fileListTable
 WHERE type = 'L'

SET @LDF = REVERSE(@LDF)
 SET @charIndex = charindex('\', @LDF)
 SET @LDF = LEFT(@LDF, @charIndex - 1)
 SET @LDF = REVERSE(@LDF)

DELETE
 FROM @dataFiles

INSERT INTO @dataFiles
 SELECT ROW_NUMBER() OVER (
 ORDER BY fileid
 ) AS rowid
 ,fileid
 ,physicalname
 FROM ##fileListTable
 WHERE type IN ('D','F')
 AND fileid <> 1

SELECT @count = count(*)
 FROM @dataFiles
 WHERE fileid <> 1

WHILE (@count > 0)
 BEGIN
 SELECT @NDF = physicalname
 FROM @dataFiles
 WHERE rowid = @count

SET @NDF = REVERSE(@NDF)
 SET @charIndex = charindex('\', @NDF)
 SET @NDF = LEFT(@NDF, @charIndex - 1)
 SET @NDF = REVERSE(@NDF)

IF (@isDataPathNull = 1)
 BEGIN
 SET @dataFilesPath = REVERSE(SUBSTRING(REVERSE((SELECT physicalname FROM @dataFiles WHERE rowid = @count)),charindex('\', REVERSE((SELECT physicalname FROM @dataFiles WHERE rowid = @count)))+1,DATALENGTH(REVERSE((SELECT physicalname FROM @dataFiles WHERE rowid = @count)))))

END

SELECT @ndfCmd = @ndfCmd + ', MOVE N''' + (
 SELECT logicalname
 FROM ##fileListTable
 WHERE type IN ('D','F')
 AND fileid = (
 SELECT fileid
 FROM @dataFiles
 WHERE rowid = @count
 )
 ) + ''' TO N''' + @dataFilesPath + '\' + @NDF + ''''

 SET @count = (@count - 1)
 END

IF (@isDataPathNull = 1)
 BEGIN
 SET @dataFilesPath = REVERSE(SUBSTRING(REVERSE((SELECT physicalname FROM ##fileListTable WHERE type = 'D' AND fileid = 1)),charindex('\', REVERSE((SELECT physicalname FROM ##fileListTable WHERE type = 'D' AND fileid = 1)))+1,DATALENGTH(REVERSE((SELECT physicalname FROM ##fileListTable WHERE type = 'D' AND fileid = 1)))))

END

IF (@isLogPathNull = 1)
 BEGIN
 SET @logFilesPath = REVERSE(SUBSTRING(REVERSE((SELECT physicalname FROM ##fileListTable WHERE type = 'L')),charindex('\', REVERSE((SELECT physicalname FROM ##fileListTable WHERE type = 'L')))+1,DATALENGTH(REVERSE((SELECT physicalname FROM ##fileListTable WHERE type = 'L')))))

END

IF (@replaceDB = 1)
 BEGIN
 IF EXISTS (SELECT name FROM master.sys.databases WHERE name = (SELECT databasename FROM ##headerTable))
 BEGIN
 SET @cmd = @cmd + '
USE [master]
ALTER DATABASE ['+ (SELECT databasename FROM ##headerTable) + '] SET SINGLE_USER WITH ROLLBACK IMMEDIATE
'
 END
 END

SET @cmd = @cmd + '
USE [master]
RESTORE DATABASE [' + (
 SELECT databasename
 FROM ##headerTable
 ) + '] FROM DISK = N''' + @backupFilesPath + '\' + @filename + ''' WITH FILE = 1, MOVE N''' + (
 SELECT logicalname
 FROM ##fileListTable
 WHERE type = 'D'
 AND fileid = 1
 ) + ''' TO N''' + @dataFilesPath + '\' + @MDF + ''', MOVE N''' + (
 SELECT logicalname
 FROM ##fileListTable
 WHERE type = 'L'
 ) + ''' TO N''' + @logFilesPath + '\'+ @LDF + '''' + @ndfCmd

IF (@replaceDB = 1)
 SET @cmd = @cmd + ', REPLACE'

IF (@recoveryDB = 0)
 SET @cmd = @cmd + ', NORECOVERY'

SET @cmd = @cmd + ', NOUNLOAD, STATS = 5
'

IF (@replaceDB = 1)
 BEGIN
 IF EXISTS (SELECT name FROM master.sys.databases WHERE name = (SELECT databasename FROM ##headerTable))
 BEGIN
 SET @cmd = @cmd + '
USE [master]
ALTER DATABASE ['+ (SELECT databasename FROM ##headerTable) + '] SET MULTI_USER WITH ROLLBACK IMMEDIATE
'
 END
 END

ContinueLoop:
 SET @ndfCmd = ''
 SET @startid = @startid + 1
END

SET @cmd = '-- Start Script --
' + @cmd + '
-- End Script --'

IF ( @exec = 1 )
 BEGIN
 EXEC (@cmd)
 END
ELSE
 BEGIN
 SELECT @cmd
 END

ExitCode:
IF((SELECT COUNT(*) from @DBList) = 0)
BEGIN
 PRINT '- - - File(s) Not Found - - -'
END

DROP TABLE ##headerTable
DROP TABLE ##fileListTable
SET NOCOUNT OFF

Bir Cevap Yazın

Aşağıya bilgilerinizi girin veya oturum açmak için bir simgeye tıklayın:

WordPress.com Logosu

WordPress.com hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap /  Değiştir )

Facebook fotoğrafı

Facebook hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap /  Değiştir )

Connecting to %s