SQL Server 數據庫基於備份文件的【一鍵還原】

1. 備份與還原的基礎說明

咱們知道在DBA的平常工做中,SQL Server 數據庫的恢復請求偶有發生,多是用做數據的追蹤,可也可能能是數據庫的災難恢復。sql

數據庫經常使用的備份命令以下:shell

----完整備份
Declare @FullFileName Varchar(200)
Declare @FileFlag varchar(20)
Set @FileFlag=REPLACE(CONVERT(VARCHAR(10), GETDATE(), 120), '-','')+ REPLACE(CONVERT(VARCHAR(10), GETDATE(), 8), ':', '')
Set @FullFileName='文檔路徑\數據庫名字_FULL'+@FileFlag+'.bak'
BackUp DataBase 數據庫名字 To Disk=@FullFileName with init

----差別備份
Declare @DiffFileName varchar(200)
Declare @FileFlag varchar(200)
Set @FileFlag=REPLACE(CONVERT(VARCHAR(10), GETDATE(), 120), '-','')+ REPLACE(CONVERT(VARCHAR(10), GETDATE(), 8), ':', '')
Set @DiffFileName='文檔路徑\數據庫名字_Diff_'+@FileFlag+'.bak'
BackUp DataBase 數據庫名字 To Disk=@DiffFileName with init,differential 

----事務日誌備份
Declare @FileName Varchar(200)
Declare @FileFlag varchar(20)
Set @FileFlag=REPLACE(CONVERT(VARCHAR(10), GETDATE(), 120), '-','')+ REPLACE(CONVERT(VARCHAR(10), GETDATE(), 8), ':', '')
Set @FileName='文檔路徑\數據庫名字_Trn_'+@FileFlag+'.trn'
BackUp Log 數據庫名字 To Disk=@FileName with init

 

備份文件的命名格式爲:數據庫名字_備份類型(Full或Diff或Trn的一種)_時間格式.文件類型(bak或trn的一種) 數據庫

其中的時間格式爲:年月日時分秒 ,例如:20190423140813。安全

例如,數據庫TestRestoreOP的備份文件以下:服務器

 

咱們花費篇章來講明備份文件的格式化,主要是由於【一鍵】還原的基礎是文件的標準化。網絡

 

相應的還原命令以下:oop

----完整備份還原
RESTORE DATABASE 數據庫名字 FROM 
DISK = '完整備份的文件'---'TTTTTTT.BAK' 
WITH NORECOVERY, MOVE '數據庫名字_Data' TO 'D:\指定路徑\數據庫名字_Data.mdf',
MOVE '數據庫名字_Log' TO 'D:\指定路徑\數據庫名字_Log.ldf'

----差別備份還原
RESTORE DATABASE 數據庫名字 FROM 
DISK = '差別備份的文件'------'SSSSSSSSS.BAK' 
WITH NORECOVERY, MOVE '數據庫名字_Data' TO 'D:\指定路徑\數據庫名字_Data.mdf',
MOVE '數據庫名字_Log' TO 'D:\指定路徑\數據庫名字_Log.ldf'

----log備份還原
RESTORE Log 數據庫名字 
FROM DISK ='事務日誌備份的文件' -----'XXXXXXXX.trn'
WITH NORECOVERY

2.遠程備份文件的【一鍵】還原

實際的生產中,咱們常將備份文件Copy至遠程服務器上,因此還原的時候,還要將這些文件Copy到指定服務上再進行還原。還有一種狀況,就是Log還原可能須要逐一還原多個日誌文件,有時候,甚至十幾個文件須要還原。spa

針對這種這種狀況,平常工做中,咱們逐漸提煉成了如下SQL,替換參數後,基本實現 一鍵還原。日誌

主要實現的功能有四點:code

(1)將遠程Server 上的指定備份路徑下的文件Copy值本地指定路徑;(若是文件以Copy值本地,這一步能夠省略,對應的代碼爲1和2部分)

(2) 將這些文件屬性讀到表BackupFile;

(3)根據文件命名的時間屬性,還原最近的一個完整備份 和一個差別備份;

(4)還原差別備份後產生的全部日誌備份。

3.代碼實現

---0 --定義要還原的數據庫名字
    DECLARE @Cmd varchar (1024)
     DECLARE @dbName sysname 
     Set @dbName='TestRestoreOP'

--- 1 --定義遠程備份文件所在目錄
    DECLARE @sourceFile NVARCHAR(500)  
    SET @sourceFile = '\\169.XXX.XXX.XXX\d$\SQL_BackFile'

----2 -- 將遠程備份的目錄,Copy至本地 D:\SQL_RestoreFile 目錄下,MAXAGE:3 表明Copy最近3天的文件
    SET @Cmd=('master.dbo.xp_cmdshell '+'''ROBOCOPY.exe  "'+@sourceFile+'" "D:\SQL_RestoreFile" *.* /E /XC /XN /X /MAXAGE:3 /MINAGE:0 ''')
    print @Cmd
    EXEC (@Cmd)

      Print '將遠程須要還原的文件Copy至本地'

----3 -- 獲取還原文件List
        DECLARE @Path VARCHAR(260)
        SET @Path = 'D:\SQL_RestoreFile'
        IF RIGHT(@Path, 1) <> '\'
         SET @Path = @Path + '\'
         Print @Path
      ----判斷表BackupFile是否已經存在,不存在則建立
          IF (SELECT COUNT(*) FROM SYS.sysobjects WHERE name='BackupFile'and xtype='U')=0
            BEGIN
                CREATE TABLE BackupFile
                (
                  id INT ,  --編號
                  directory VARCHAR(260) ,  --路徑
                  depth INT , --深度,相對與@path
                  IsFile BIT ,
                  filename VARCHAR(260),
                  IsRestore int ,--是否還原
                )--0文件夾1文件名成
            END 

            Truncate table BackupFile

      -----判斷表TMP_BackupFile是否已經存在,存在則刪除再建立
          IF (SELECT COUNT(*) FROM SYS.sysobjects WHERE name='TMP_BackupFile'and xtype='U')<>0
            BEGIN
                DROP TABLE TMP_BackupFile  
            END 
        CREATE TABLE TMP_BackupFile
            (
              id INT IDENTITY ,  --編號
              directory VARCHAR(260) ,  --路徑
              depth INT , --深度,相對與@path
              IsFile BIT ,
              filename VARCHAR(260),
              IsRestore int ,--是否還原
            )--0文件夾1文件名成


       ----將@Path 目錄下結構讀入到表TMP_BackupFile中
        INSERT  TMP_BackupFile
                ( directory ,
                  depth ,
                  IsFile
                )
        
        EXEC master.dbo.xp_dirtree @path = @Path, @depth = 0, @file = 1

        update TMP_BackupFile set filename=directory,IsRestore=0

       Print '將須要還原的文件信息讀入到表TMP_BackupFile中'


        -----設置不須要還原的數據庫文件,即刪除
         DELETE FROM dbo.TMP_BackupFile WHERE directory  NOT LIKE '%'+@dbName+'%'

        ----設置刪除不符合日期規則的文件
        DELETE FROM dbo.TMP_BackupFile WHERE  left(right([filename],18),14)<'20190413015000'

        -----更新目錄

        UPDATE  TMP_BackupFile
        SET     directory = @Path + directory
        WHERE   depth = 1

        ------
        if exists(  select * from TMP_BackupFile  WHERE   depth > 1)
        begin

        Print 'Error:備份文件所在的路徑不對,或者@Path包含了不該該存在的文件夾目錄!'
        
        end  
        -------

        INSERT INTO BackupFile (directory, depth, IsFile, [filename], IsRestore)
        SELECT B.directory, B.depth, B.IsFile, B.[filename], B.IsRestore FROM TMP_BackupFile B 
        left join BackupFile e on B.[filename]=e.[filename] where e.[filename] is null 


---4 --定義5/6/7 步驟須要的參數

    DECLARE @filename NVARCHAR(500) 
    DECLARE @backupPath NVARCHAR(500)


-- 5 -- 找到須要還原的完整備份文件,進行完整還原

   SELECT top 1  @filename =[filename] FROM BackupFile WHERE IsRestore=0 AND directory LIKE '%FULL%.bak' ORDER BY left(right([filename],18),14) desc
   Print @filename 
   
   Print 'Msg:完整備份文件:' + @filename  + '開始還原!'

   SELECT @backupPath=directory 
   FROM BackupFile WHERE filename=@filename AND  IsRestore=0
   print @dbName
   SET @cmd = 'RESTORE DATABASE [' + @dbName + '] FROM DISK = '''  
       + @backupPath + ''' WITH  FILE = 1,  MOVE N'''+@dbName+''' TO N''D:\sql_data\'+@dbName+'.MDF'', MOVE N'''+@dbName+'_Log'' TO N''D:\sql_log\'+@dbName+'.LDF'',NORECOVERY,    NOUNLOAD,  STATS = 5' 
   exec (@cmd)
   PRINT @cmd

   UPDATE BackupFile SET IsRestore=1 WHERE filename=@filename AND  IsRestore=0

   Print 'Msg:完整備份文件:' + @filename  + '還原完成!'

-- 6 --- 找到須要還原的差別備份文件,進行增量還原

    SELECT top 1 @filename=[filename] FROM BackupFile WHERE IsRestore=0 AND directory LIKE '%Diff%.bak'  ORDER BY left(right([filename],18),14) desc
    print @filename

    Print 'Msg:獲取得知須要還原的差別備份文件:' + @filename  + ',此時將不須要還原的差別文件/日誌文件設置爲不須要還原'
    update  BackupFile  set IsRestore=10  
    WHERE IsRestore=0 AND 
    (directory LIKE '%Diff%.bak' or directory LIKE '%TRN%.TRN'  ) and left(right([filename],18),14)<left(right( @filename,18),14)

      Print 'Msg:差別備份文件:' + @filename  + '開始還原!'

    SELECT @backupPath=directory FROM BackupFile WHERE filename=@filename AND  IsRestore=0
   
    SET @cmd = 'RESTORE DATABASE [' + @dbName + '] FROM DISK = '''  
       + @backupPath + ''' WITH NORECOVERY' 
    exec(@cmd)
    PRINT @cmd

    UPDATE BackupFile SET IsRestore=1 WHERE filename=@filename AND  IsRestore=0

     Print 'Msg:差別備份文件:' + @filename  + '還原完成!'

-- 7  --日誌備份文件還原
    DECLARE filenames CURSOR FOR  
        SELECT [filename] FROM BackupFile WHERE IsRestore=0 AND directory LIKE '%TRN%.TRN'  ORDER BY left(right([filename],18),14) asc
    OPEN filenames  
    -- Loop through all the files for the database  
    FETCH NEXT FROM filenames INTO @filename  
    WHILE @@FETCH_STATUS = 0  
    BEGIN  

       Print 'Msg:日誌備份文件:' + @filename  + '開始還原!'
    
       SELECT @backupPath=directory FROM BackupFile WHERE filename=@filename AND  IsRestore=0
       SET @cmd = 'RESTORE LOG [' + @dbName + '] FROM DISK = '''  
           +@backupPath+ ''' WITH NORECOVERY' 
       exec(@cmd)
   
       UPDATE BackupFile SET IsRestore=1 WHERE filename=@filename AND  IsRestore=0

        Print 'Msg:日誌備份文件:' + @filename  + '還原完成!'

       PRINT @cmd
       FETCH NEXT FROM filenames INTO @filename  
    END 
    CLOSE filenames  
    DEALLOCATE filenames  

-- 8 -- 將數據庫的狀態由真正還原Restore正常狀態! 

 Print '將數據庫的狀態由真正還原Restore正常狀態!'
SET @cmd = 'RESTORE DATABASE [' + @dbName + '] WITH RECOVERY' 
exec(@cmd)
PRINT @cmd

Print '數據庫全部的還原操做都已完成!'

 

 

若是在您工做中也有相似需求,須要執行上述代碼,則須要替換的參數以下

須要替換的參數數據
參數 表明含義
@dbName 需還原的數據庫名字,本例爲;
TestRestoreOP
@sourceFile
備份文件在遠程Server路徑;本例爲
\\169.XXX.XXX.XXX\d$\SQL_BackFile
沒有設置參數 備份文件copy至本地的路徑;本例爲
D:\SQL_RestoreFile
 沒有設置參數
設置刪除不符合日期規則的文件,指的是把舊的文件也Copy到本地了,這還原表中因刪除;本例爲
20190413015000
 沒有設置參數
設置還原數據庫的數據文件所在文檔路徑:本例爲 D:\sql_data\。建議不要修改,執行前請先建立。
 沒有設置參數
設置還原數據庫的日誌文件所在文檔路徑;本例爲 D:\sql_log\
。建議不要修改,執行前請先建立。

 

4.ROBOCOPY.exe知識補充

備份文件的遠程Copy經過ROBOCOPY.exe來實現。

 Robocopy.exe 是 微軟在Windows server 2003 Resource Kit Tools 裏面提供的程序來作備份的,Vista,Win2008已經自帶了。Microsoft Windows 中內置的傳統的「複製和粘貼」功能有一些侷限性:它在執行簡單的任務(將一個文檔從一個目錄移動到另外一個目錄等)時處理得還好,但缺少 IT 專業人員在工做場所所需的高級功能。例如,複製和粘貼操做不包括任何高級復原功能,因此不容許從短暫的網絡中斷後進行恢復。Robocopy 支持更多重要的文件複製任務,從而可以簡化工做。Robocopy 還容許保留全部相關文件信息,包括日期和時間戳、安全訪問控制列表 (ACL) 及更多內容。[更多內容請參考網絡分享]

如今主要留意下ROBOCOPY.exe的一些參數,由於咱們在代碼中有用到他們。

參數 含義
/MAXAGE 最長的文件存在時間 - 排除早於 n 天/日期的文件。(n表明指定參數)
/MINAGE 最短的文件存在時間 - 排除晚於 n 天/日期的文件。
/S 複製子目錄,但不復制空的子目錄。
/XC 排除已更改的文件。
/XN 排除較新的文件。
/X 報告全部多餘的文件,而不僅是選中的文件。

 

 

感謝:以上代碼由做者本人和同事Fly Chen共同完成。

未經做者贊成不得轉載,謝謝配合!!!

相關文章
相關標籤/搜索