Ricostruire la sequenza di ripristino

di Luca Bianchi, in SQL Server,

Nella definizione di una strategia di disaster recovery uno dei principali fattori da tenere in considerazione è avere ben chiare le modalità di ripristino dei dati ed avere coscienza non solo della corretta sequenza di ripristino ma anche dei tempi attesi è un aspetto di primaria importanza. Il più delle volte si perde del tempo prezioso nel ricercare, all'interno di un device di backup, la posizione dei vari backup completi, differenziali e del t-log al fine di ricostruire la corretta sequenza di ripristino. Personalmente mi sono costruito questo script

================================

DECLARE @file VARCHAR(255)

SET @file = '\\server\cartella\file.bak'

DECLARE @sql VARCHAR(2048),
@data DATETIME,
@pos SMALLINT,
@logicfile SYSNAME,
@physfile VARCHAR(255),
@masterfile VARCHAR(255),
@db SYSNAME

SET NOCOUNT ON

IF OBJECT_ID('tempdb..#header') IS NOT NULL
DROP TABLE #header

IF OBJECT_ID('tempdb..#filelist') IS NOT NULL
DROP TABLE #filelist

CREATE TABLE #header
(
BackupName nvarchar(128) NULL ,
BackupDescription nvarchar(255) NULL ,
BackupType smallint NULL,
ExpirationDate datetime NULL ,
Compressed tinyint NULL ,
Position smallint NULL ,
DeviceType tinyint NULL ,
UserName nvarchar(128) NULL ,
ServerName nvarchar(128) NULL ,
DatabaseName nvarchar(128) NULL ,
DatabaseVersion int NULL ,
DatabaseCreationDate datetime NULL ,
BackupSize numeric(20,0) NULL ,
FirstLSN numeric(25,0) NULL ,
LastLSN numeric(25,0) NULL ,
CheckpointLSN numeric(25,0) NULL ,
DatabaseBackupLSN numeric(25,0) NULL ,
BackupStartDate datetime NULL ,
BackupFinishDate datetime NULL ,
SortOrder smallint NULL ,
CodePage smallint NULL ,
UnicodeLocaleId int NULL ,
UnicodeComparisonStyle int NULL ,
CompatibilityLevel tinyint NULL ,
SoftwareVendorId int NULL ,
SoftwareVersionMajor int NULL ,
SoftwareVersionMinor int NULL ,
SoftwareVersionBuild int NULL ,
MachineName nvarchar(128) NULL ,
Flags int NULL ,
BindingID uniqueidentifier NULL ,
RecoveryForkID uniqueidentifier NULL ,
Collation nvarchar(128) NULL ,
FamilyGUID uniqueidentifier NULL ,
HasBulkLoggedData bit NULL ,
IsSnapshot bit NULL ,
IsReadOnly bit NULL ,
IsSingleUser bit NULL ,
HasBackupChecksums bit NULL ,
IsDamaged bit NULL ,
BeginsLogChain bit NULL ,
HasIncompleteMetaData bit NULL ,
IsForceOffline bit NULL ,
IsCopyOnly bit NULL ,
FirstRecoveryForkID uniqueidentifier NULL ,
ForkPointLSN numeric(25,0) NULL ,
RecoveryModel nvarchar(60) NULL ,
DifferentialBaseLSN numeric(25,0) NULL ,
DifferentialBaseGUID uniqueidentifier NULL ,
BackupTypeDescription nvarchar(60) NULL ,
BackupSetGUID uniqueidentifier NULL
)

CREATE TABLE #filelist
(
LogicalName nvarchar(128) NOT NULL ,
PhysicalName nvarchar(260) NOT NULL ,
Type char(1) NOT NULL ,
FileGroupName nvarchar(128) NULL ,
Size decimal(20,0) NULL ,
MaxSize decimal(20,0) NULL ,
FileID bigint NULL ,
CreateLSN numeric(25,0) NULL ,
DropLSN numeric(25,0) NULL ,
UniqueID uniqueidentifier NULL ,
ReadOnlyLSN numeric(25,0) NULL ,
ReadWriteLSN numeric(25,0) NULL ,
BackupSizeInBytes bigint NULL ,
SourceBlockSize int NULL ,
FileGroupID int NULL ,
LogGroupGUID uniqueidentifier NULL ,
DifferentialBaseLSN numeric(25,0) NULL ,
DifferentialBaseGUID uniqueidentifier ,
IsReadOnly bit ,
IsPresent bit
)

SET @sql = 'RESTORE HEADERONLY FROM DISK = ''' + @file + ''''

INSERT #header
EXEC (@sql)

SELECT TOP 1 @pos = Position, @data = BackupStartDate , @db = DatabaseName
FROM #header
WHERE BackupType = 1
ORDER BY BackupStartDate DESC

DELETE #header
WHERE Position <= @pos

SET @sql = 'RESTORE FILELISTONLY FROM DISK = ''' + @file + ''' WITH FILE = ' + CONVERT(VARCHAR(5), @pos)

INSERT #filelist
EXEC (@sql)

SET @sql = 'RESTORE DATABASE *nomedb* FROM DISK = ''' + @file + '''' + CHAR(13) +
'WITH '

SELECT @masterfile = RTRIM(filename)
FROM master..sysfiles
WHERE fileid = 1

DECLARE cur CURSOR FOR
SELECT LogicalName, RIGHT(PhysicalName, CHARINDEX('\', REVERSE(PhysicalName)) -1)
FROM #filelist

OPEN cur

FETCH NEXT FROM cur INTO @logicfile, @physfile

WHILE @@FETCH_STATUS = 0
BEGIN
SET @physfile = REPLACE(@masterfile, 'master.mdf', @physfile)
SET @sql = @sql + 'MOVE ''' + @logicfile + ''' TO ''' + @physfile + ''', ' + CHAR(13) + ' '
FETCH NEXT FROM cur INTO @logicfile, @physfile
END

CLOSE cur
DEALLOCATE cur

SET @sql = @sql + 'FILE = ' + CONVERT(VARCHAR(5), @pos) + ', ' + CHAR(13) + ' '
SET @sql = @sql + 'NORECOVERY'

PRINT '--Ripristino del full backup del ' + CONVERT(VARCHAR(20), @data, 113)
PRINT @sql
PRINT 'GO' + CHAR(13) + CHAR(13)

SELECT TOP 1 @pos = Position, @data = BackupStartDate
FROM #header
WHERE BackupType = 5
ORDER BY BackupStartDate DESC

IF @@ROWCOUNT > 0
BEGIN
DELETE #header
WHERE Position <= @pos

 SET @sql = 'RESTORE DATABASE *nomedb* FROM DISK = ''' + @file + '''' + CHAR(13) +
'WITH FILE = ' + CONVERT(VARCHAR(5), @pos) + ', ' + CHAR(13) + ' ' +
'NORECOVERY'

 PRINT '--Ripristino del diff backup del ' + CONVERT(VARCHAR(20), @data, 113)
PRINT @sql
PRINT 'GO' + CHAR(13) + CHAR(13)
END

WHILE EXISTS (SELECT 1 FROM #header)
BEGIN
SELECT TOP 1 @pos = Position, @data = BackupStartDate
FROM #header
WHERE BackupType = 2
ORDER BY Position ASC

 --PRINT CONVERT(varchar(4), @logfile)
DELETE #header
WHERE Position = @pos

 SET @sql = 'RESTORE LOG *nomedb* FROM DISK = ''' + @file + '''' + CHAR(13) +
'WITH FILE = ' + CONVERT(VARCHAR(5), @pos) + ', ' + CHAR(13) + ' ' +
'NORECOVERY'

 PRINT '--Ripristino del t-log del ' + CONVERT(VARCHAR(20), @data, 113)
PRINT @sql
PRINT 'GO' + CHAR(13) + CHAR(13)
END

PRINT '--Rende il database accessibile'
PRINT 'RESTORE DATABASE *nomedb* WITH RECOVERY'
PRINT 'GO' + CHAR(13) + CHAR(13)

================================

che vi consiglio di portare sempre con voi nella chiavetta USB.

Attenzione che lo script di cui sopra funziona con SQL Server 2005. In SQL Server 2000 differisce l'output dell'istruzione RESTORE HEADERONLY e quello dell'istruzione RESTORE FILELISTONLY ma è sufficiente modificare la definizione delle tabelle temporanee come indicato di seguito per utilizzarlo anche con SQL Server 2000

================================

CREATE TABLE #header
(
BackupName nvarchar(128) NULL,
BackupDescription nvarchar(255) NULL,
BackupType smallint NULL,
ExpirationDate datetime NULL,
Compressed tinyint NULL,
Position smallint NULL,
DeviceType tinyint NULL,
UserName nvarchar(128) NULL,
ServerName nvarchar(128) NULL,
DatabaseName nvarchar(128) NULL,
DatabaseVersion int NULL,
DatabaseCreationDate datetime NULL,
BackupSize decimal(20,0) NULL,
FirstLSN decimal(25,0) NULL,
LastLSN decimal(25,0) NULL,
CheckpointLSN decimal(25,0) NULL,
DatabaseBackupLSN decimal(25,0) NULL,
BackupStartDate datetime NULL,
BackupFinishDate datetime NULL,
SortOrder smallint NULL,
CodePage smallint NULL,
UnicodeLocaleId int NULL,
UnicodeComparisonStyle int NULL,
CompatibilityLevel tinyint NULL,
SoftwareVendorId int NULL,
SoftwareVersionMajor int NULL,
SoftwareVersionMinor int NULL,
SoftwareVersionBuild int NULL,
MachineName nvarchar(128) NULL,
Flags int NULL,
BindingID uniqueidentifier NULL,
RecoveryForkID uniqueidentifier NULL,
Collation nvarchar(128) NULL
)

CREATE TABLE #filelist
(
LogicalName nvarchar(128) NOT NULL,
PhysicalName nvarchar(260) NOT NULL,
Type char(1) NOT NULL,
FileGroupName nvarchar(128) NULL,
Size decimal(20,0) NULL,
MaxSize decimal(20,0) NULL
)

================================

Infine vi segnalo questo sondaggio che la rivista SQL Server Magazine fece qualche anno fa. Non credo che le cose siano molto cambiate da allora ed è estremamente preoccupante leggere che il 70% degli intervistati non si preoccupa affatto della procedura di ripristino dei dati che, ricordo, è parte fondamentale (direi vitale) della strategia di disaster recovery e non esagero dicendo che da essa può dipendere il futuro di ogni azienda.

Bye

Commenti

Visualizza/aggiungi commenti

| Condividi su: Twitter, Facebook, LinkedIn

Per inserire un commento, devi avere un account.

Fai il login e torna a questa pagina, oppure registrati alla nostra community.

Nella stessa categoria
I più letti del mese