問題
數(shù)據(jù)庫管理員眼下的一個挑戰(zhàn)是備份和恢復(fù)數(shù)據(jù)庫。備份在自動調(diào)度表中完成,但是恢復(fù)可以采取很多不同的版本,你可能需要恢復(fù)一個產(chǎn)品數(shù)據(jù)庫,恢復(fù)一個發(fā)展包,或者測試數(shù)據(jù)庫,或者只在另外的地方創(chuàng)建數(shù)據(jù)庫副本。有一些自動執(zhí)行恢復(fù)過程和創(chuàng)建腳本的方法,但是這個方法顯示了一種方式,那就是只讀取存在于備份文件中的目錄的內(nèi)容。
專家解答
以下是讀取目錄中的內(nèi)容和創(chuàng)建需要通過執(zhí)行來恢復(fù)數(shù)據(jù)庫的恢復(fù)命令的一種簡單方法。這個腳本可以用于全部備份,差異備份和事務(wù)日志備份。
在我們開始之前,下面的腳本假設(shè)情況如下:
1、 恢復(fù)的數(shù)據(jù)庫擁有和備份數(shù)據(jù)庫一樣的名稱。
2、 恢復(fù)的數(shù)據(jù)庫和備份數(shù)據(jù)庫存儲在相同的位置。
3、 文件名具有以下的格式
dbName_YYYYMMDDHHMM.xxx
4、 文件擴(kuò)展名如下
全部備份 – BAK
差異備份 – DIF
事務(wù)日志備份 – TRN
5、 XP_CMDSHELL 是可用的
6、 不存在可能破壞恢復(fù)鏈的缺失的事務(wù)日志
所以,讓我們按照下面的步驟來創(chuàng)建自己的備份:
- 在午夜進(jìn)行全部備份
- 早上3:15開始每三個小時進(jìn)行一次差異備份
- 早上1點開始每半個小時進(jìn)行一次日志備份
在上午九點,我們可能會得到以下創(chuàng)建于2008年9月10日的備份文件,這個備份文件遵從以上規(guī)則,命名為Customer。
Customer_200809100000.BAK
Customer_200809100100.TRN
Customer_200809100130.TRN
Customer_200809100200.TRN
Customer_200809100230.TRN
Customer_200809100300.TRN
Customer_200809100315.DIF
Customer_200809100330.TRN
Customer_200809100400.TRN
Customer_200809100430.TRN
Customer_200809100500.TRN
Customer_200809100530.TRN
Customer_200809100600.TRN
Customer_200809100615.DIF
Customer_200809100630.TRN
Customer_200809100700.TRN
Customer_200809100730.TRN
Customer_200809100800.TRN
Customer_200809100830.TRN
Customer_200809100900.TRN
如果我們想在早上九點對最新的全部備份,差異備份和事務(wù)日志備份做一個恢復(fù),那么我們需要恢復(fù)以下的文件:
Customer_200809100000.BAK
Customer_200809100615.DIF
Customer_200809100630.TRN
Customer_200809100700.TRN
Customer_200809100730.TRN
Customer_200809100800.TRN
Customer_200809100830.TRN
Customer_200809100900.TRN
下面的腳本會讀取目錄并且為我們創(chuàng)建恢復(fù)腳本。僅有的兩個需要改變的參數(shù)是@dbName 和 @backupPath。
USE Master;
GO
SET NOCOUNT ON
-- 1 - Variable declaration
DECLARE @dbName sysname
DECLARE @backupPath NVARCHAR(500)
DECLARE @cmd NVARCHAR(500)
DECLARE @fileList TABLE (backupFile NVARCHAR(255))
DECLARE @lastFullBackup NVARCHAR(500)
DECLARE @lastDiffBackup NVARCHAR(500)
DECLARE @backupFile NVARCHAR(500)
-- 2 - Initialize variables
SET @dbName = 'Customer'
SET @backupPath = 'D:\SQLBackups\'
-- 3 - get list of files
SET @cmd = 'DIR /b ' + @backupPath
INSERT INTO @fileList(backupFile)
EXEC master.sys.xp_cmdshell @cmd
-- 4 - Find latest full backup
SELECT @lastFullBackup = MAX(backupFile)
FROM @fileList
WHERE backupFile LIKE '%.BAK'
AND backupFile LIKE @dbName + '%'
SET @cmd = 'RESTORE DATABASE ' + @dbName + ' FROM DISK = '''
+ @backupPath + @lastFullBackup + ''' WITH NORECOVERY, REPLACE'
PRINT @cmd
-- 4 - Find latest diff backup
SELECT @lastDiffBackup = MAX(backupFile)
FROM @fileList
WHERE backupFile LIKE '%.DIF'
AND backupFile LIKE @dbName + '%'
AND backupFile > @lastFullBackup
-- check to make sure there is a diff backup
IF @lastDiffBackup IS NOT NULL
BEGIN
SET @cmd = 'RESTORE DATABASE ' + @dbName + ' FROM DISK = '''
+ @backupPath + @lastDiffBackup + ''' WITH NORECOVERY'
PRINT @cmd
SET @lastFullBackup = @lastDiffBackup
END
-- 5 - check for log backups
DECLARE backupFiles CURSOR FOR
SELECT backupFile
FROM @fileList
WHERE backupFile LIKE '%.TRN'
AND backupFile LIKE @dbName + '%'
AND backupFile > @lastFullBackup
OPEN backupFiles
-- Loop through all the files for the database
FETCH NEXT FROM backupFiles INTO @backupFile
WHILE @@FETCH_STATUS = 0
BEGIN
SET @cmd = 'RESTORE LOG ' + @dbName + ' FROM DISK = '''
+ @backupPath + @backupFile + ''' WITH NORECOVERY'
PRINT @cmd
FETCH NEXT FROM backupFiles INTO @backupFile
END
CLOSE backupFiles
DEALLOCATE backupFiles
-- 6 - put database in a useable state
SET @cmd = 'RESTORE DATABASE ' + @dbName + ' WITH RECOVERY'
PRINT @cmd |
如果你在一個查詢窗口中運行以上代碼,并且假設(shè)以上列出的文件是存在的,那么你將會得到下面的輸出結(jié)果。在這一時刻,你可以把這些代碼復(fù)制和粘貼到另一個查詢窗口并且執(zhí)行查詢來做真正的恢復(fù)。
正如你所看到的,它做的是全部備份,最新的差異備份接著是所有的事務(wù)日志。這個腳本最后也使用了WITH RECOVERY來使數(shù)據(jù)庫保持可用的狀態(tài)。
|