SQL Server 批量主分區備份(One Job)

一.本文所涉及的內容(Contents)

  1. 本文所涉及的內容(Contents)
  2. 背景(Contexts)
  3. 案例分析(Case)
  4. 實現代碼(SQL Codes)
  5. 主分區完整、差別還原(Primary Backup And Restore)
  6. 參考文獻(References)

二.背景(Contexts)

  在個人數據庫實例中,有不少下圖所示的數據庫,這些數據庫的名稱是有規律的,每一個數據庫包含的表都是相同的,其中2個表是相似流水記錄的表,表的數據量會比較大,佔用的空間有幾十G到上百G不等,這2個表相對於其它的配置表來講是比較不重要的。html

  如今有一個需求就是對數據庫進行備份,容許丟失這兩個表的數據,保留重要的配置表數據,你是否遇到過一樣的問題呢?這個時候你會怎麼作呢?你有什麼方案呢?有什麼方法能夠快速備份這些數據庫呢?sql

wps_clip_image-30433

(Figure1:數據庫列表)shell

閱讀本文以前你能夠先參考:SQL Server 批量完整備份數據庫

 

三.案例分析(Case)

  經過上面的描述,其中很重要的一點就是每一個數據庫中有2個大表,並且這些數據是不重要的,那麼咱們對這2個大表作表分區,把大數據放到其它文件組中,只留重要的配置表在主文件組(PRIMARY)中,接着就能夠對主文件組進行備份,這樣既知足了備份重要表數據,並且不會形成備份文件過大、佔用磁盤空間、備份時間過長等問題。服務器

  肯定了方向以後咱們接着考慮做業的問題,經過做業備份相似Figure1的數據庫,有下面兩種方案可供選擇:測試

wps_clip_image-31239

(Figure2:做業列表)大數據

wps_clip_image-21511

(Figure3:做業列表)spa

  Figure2是一個方案,這些做業是能夠自動化建立,可是會用到批處理,代碼會複雜一點,惟一的缺點就是當新建立了數據庫,是沒法自動備份的(不過能夠經過專門建立一個監控數據庫的新建、刪除狀態的Job來解決這個問題)詳情請參考:SQL Server 批量主分區備份(Multiple Jobs)3d

  Figure3就是咱們這篇文章須要講述的方案,這裏把全部的數據庫的備份都集中到一個做業中,這個方案有如下缺點:代理

    1) 整個備份過程是串行的;

    2) 若是沒有異常處理,那麼後面的數據庫就沒有辦法備份了;

    3) 在做業執行的時候對服務器壓力比較大(沒有分散執行時間);

    4) 作自己的msdb數據庫中記錄的做業日誌也沒有那麼清晰,排錯比較困難(只有整個做業的信息,msdb.dbo.sysjobhistory的message字段保存不了太多信息),須要本身建立表進行記錄;

  儘管有以上的缺點,可是也是有優勢的:當新建立了一個相似的數據庫(業務須要),這個時候做業也會備份這個數據,不用人工去建立做業;另外還有一個,就是當數據庫多而小的時候,這個方案特別有用;下面就來說講這個Job實現的具體步驟。

 

四.實現代碼(SQL Codes)

實現步驟概要:

  1. 批量建立文件夾;

  2. 建立維護表:[JobLog]和[ErrorLog];

  3. 建立備份全部數據庫的SQL腳本;

  4. 建立Job執行上面的腳本;

 

(一) 爲了方便管理備份文件,咱們爲每一個數據庫建立單獨的文件夾,下面的SQL代碼實現根據數據庫批量建立數據庫名對應的文件夾,使用了遊標循環數據庫名進行建立文件夾,執行cmd命令須要開啓數據庫的xp_cmdshell開關;

--批量建立文件夾
EXEC sp_configure 'show advanced options', 1
RECONFIGURE
EXEC sp_configure 'xp_cmdshell', 1
RECONFIGURE

DECLARE @DBName VARCHAR(100)
DECLARE @SQL VARCHAR(1000)

DECLARE CurDBName CURSOR FOR
    SELECT name FROM sys.databases WHERE name LIKE '%Opinion%' AND STATE =0

OPEN CurDBName
    FETCH NEXT FROM CurDBName INTO @DBName
    
    WHILE @@FETCH_STATUS = 0
    BEGIN
        SET @SQL = 'mkdir E:\DBBackup\' + @DBName
        EXEC xp_cmdshell @SQL
        
        FETCH NEXT FROM CurDBName INTO @DBName
    END
CLOSE CurDBName
DEALLOCATE CurDBName

EXEC sp_configure 'show advanced options', 0
RECONFIGURE
EXEC sp_configure 'xp_cmdshell', 0
RECONFIGURE

執行上面的腳本後,會在E:\DBBackup\目錄下建立以下圖所示的文件夾:

wps_clip_image-18848

(Figure4:建立的文件夾)

 

(二) 對備份的維護,我但願能夠了解到全部數據庫的備份狀況,因此下面建立2個維護表:[JobLog]和[ErrorLog],這兩個表用於記錄做業的執行狀況,經過這兩個表,能夠實現如Figure五、Figure6的效果;

--做業記錄表
USE [msdb]
GO
CREATE TABLE [dbo].[JobLog](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [DB_Name] [varchar](50) NULL,
    [Backup_Date] [int] NULL,
    [Backup_Time] [int] NULL,
    [Backup_Duration] [int] NULL,
    [Backup_Type] [char](4) NULL,
 CONSTRAINT [PK_JobLog] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

--錯誤記錄表
USE [msdb]
GO
CREATE TABLE [dbo].[ErrorLog](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [DB_Name] [varchar](50) NOT NULL,
    [Backup_Time] [datetime] NOT NULL CONSTRAINT [DF_ErrorLog_Backup_Time]  DEFAULT (getdate()),
    [Messages] [nvarchar](500) NULL,
 CONSTRAINT [PK_ErrorLog] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

 

(三) 下面的代碼實現了主分區完整備份和主分區差別備份(主分區可參考:SQL Server 維護計劃備份主分區),當是星期一的深夜的時候,咱們作完整備份,若是是其它時候咱們就作差別備份,具體是何時,這個就經過計劃裏面的時候來控制了(計劃的執行時間爲星期1、星期3、星期五,這就表明星期一深夜作了完整備份、星期三和星期五分別作了差別備份)。(備份實踐可參考:SQL Server 2008 維護計劃實現數據庫備份

  下面是生成的備份文件命名的範例,這樣的備份文件的命名能夠方便維護,並且直觀知道備份文件建立的時間,能夠精確到秒,文件名重複的概率不大;

DBName _Primary_Full_2013_01_14_002007.bak

DBName_Primary_Diff_2013_01_16_002034.bak

  下面是整個批量備份數據庫的核心SQL腳本,若是你是建立維護計劃,那能夠把這個SQL放到「執行 T-SQL 語句」任務,若是是建立Job的,能夠放到做業的步驟裏;

--批量備份數據庫
DECLARE @DBName VARCHAR(100)
DECLARE @CurrentTime VARCHAR(50)
DECLARE @FileName VARCHAR(200)
DECLARE @WithType CHAR(20)
DECLARE @Backup_Date VARCHAR(50)
DECLARE @Backup_Time VARCHAR(50)
DECLARE @Backup_Duration VARCHAR(50)
DECLARE @Backup_Start DATETIME
DECLARE @Backup_End DATETIME
DECLARE @BackupType CHAR(4)
DECLARE @SQL VARCHAR(MAX)

--防止做業遺漏備份
INSERT INTO [msdb].[dbo].[JobLog]([DB_Name],[Backup_Date],[Backup_Time],[Backup_Duration],[Backup_Type])
SELECT name,0,0,0,NULL FROM sys.databases WHERE name LIKE '%Opinion%' AND STATE =0
AND name NOT IN (SELECT DISTINCT [DB_Name] FROM [msdb].[dbo].[JobLog])
ORDER BY name

DECLARE CurDBName CURSOR FOR
    SELECT name FROM sys.databases WHERE name LIKE '%Opinion%' AND STATE =0 ORDER BY name

OPEN CurDBName
    FETCH NEXT FROM CurDBName INTO @DBName

    WHILE @@FETCH_STATUS = 0
    BEGIN
        --Execute Backup
        --捕獲異常
        BEGIN TRY
            PRINT @DBName
            SET @CurrentTime = REPLACE(REPLACE(REPLACE(CONVERT(VARCHAR, GETDATE(), 120 ),'-','_'),' ','_'),':','')
            IF(DATEPART(DW, GETDATE()) = 2)--星期一
            BEGIN
                SET @FileName = 'E:\DBBackup\'+@DBName+'\'+@DBName+'_Primary_Full_' + @CurrentTime+'.bak'
                SET @WithType = ' FORMAT'
                SET @BackupType = 'Full'
            END
            ELSE
            BEGIN
                SET @FileName = 'E:\DBBackup\'+@DBName+'\'+@DBName+'_Primary_Diff_' + @CurrentTime+'.bak'
                SET @WithType = ' DIFFERENTIAL,FORMAT'
                SET @BackupType = 'Diff'
            END

            SET @Backup_Start = GETDATE()
            SET @SQL = '
            --1設置完整模式
            ALTER DATABASE ['+@DBName+'] SET RECOVERY FULL WITH NO_WAIT;
            --2備份主分區
            BACKUP DATABASE ['+@DBName+']
            FILEGROUP=''PRIMARY'' TO DISK='''+@FileName+''' WITH '+@WithType+';
            --3設置簡單模式
            ALTER DATABASE ['+@DBName+'] SET RECOVERY SIMPLE WITH NO_WAIT;
            '
            EXEC(@SQL)

            SET @Backup_End = GETDATE()
            SET @Backup_Date = CONVERT(VARCHAR, GETDATE(),112)
            SET @Backup_Time = REPLACE(CONVERT(VARCHAR, GETDATE(),24),':','')
            SET @Backup_Duration = CONVERT(VARCHAR,DATEDIFF(ss,@Backup_Start,@Backup_End))
            PRINT @Backup_Date +@Backup_Time +@Backup_Duration
            SET @SQL = '
            INSERT INTO [msdb].[dbo].[JobLog]([DB_Name],[Backup_Date],[Backup_Time],[Backup_Duration],[Backup_Type])
                VALUES('''+@DBName+''','+@Backup_Date+','+@Backup_Time+','+@Backup_Duration+','''+@BackupType+''');
            '
            EXEC(@SQL)
        END TRY
        BEGIN CATCH
            INSERT INTO [dbo].[ErrorLog]([DB_Name],[ErrorMessage])
            VALUES(@DBName,ERROR_MESSAGE())
            --ROLLBACK TRANSACTION
        END CATCH

        --Get Next DataBase
        FETCH NEXT FROM CurDBName INTO @DBName
    END
CLOSE CurDBName
DEALLOCATE CurDBName

  這個備份腳本中使用了遊標循環獲取數據庫名進行備份,在【--防止做業遺漏備份】標籤的SQL語句是爲了保證記錄表[JobLog]每次執行都有新的記錄,即便備份失敗(如何查看後面會講到)也能夠觀察到對應的記錄;

  腳本中加入了異常處理,能夠有效的防止某個數據庫備份失敗後,後面數據庫的備份不受影響,把異常信息插入到[ErrorLog]。

  SQL代碼裏面強制了星期一進行主分區的完整備份,其它何時作差別備份,這個就徹底由做業中計劃來控制(若是你想,你能夠經過做業中的計劃來調整天天都進行差別備份)。

 

(四) 下面的代碼實現了刪除備份文件,從下面的代碼實現刪除14天以前的備份文件,這個能夠做爲第三步驟的下一個步驟,可是須要注意有相應的機制能夠檢測到備份失敗的數據庫,否則一段時間備份都失敗了,會形成最後沒有了備份文件(能夠經過郵件查詢[ErrorLog]進行預警,能夠參考:SQL Server 建立數據庫郵件

--刪除14天以前的備份文件
DECLARE @DeleteDate DATETIME
SET @DeleteDate = DATEADD(DAY, -14, GETDATE())

EXECUTE MASTER.SYS.XP_DELETE_FILE
0,
N'E:\DBBackup\',
N'bak',
@DeleteDate

 

(五) 查看做業的運行狀況;

--行轉列(備份類型)
DECLARE @s NVARCHAR(MAX)
SET @s=''
SELECT @s=@s+','+quotename([Backup_Date])+'=MAX(CASE WHEN [Backup_Date]='+quotename([Backup_Date],'''')+' THEN [Backup_Type] ELSE NULL END)'
FROM [msdb].[dbo].[JobLog] GROUP BY [Backup_Date] ORDER BY [Backup_Date]
PRINT @s
EXEC('SELECT [DB_Name] '+@s+' FROM [msdb].[dbo].[JobLog]
GROUP BY [DB_Name] ORDER BY [DB_Name]')

wps_clip_image-5181

(Figure5:做業備份類型)

--行轉列(執行時間)
DECLARE @s NVARCHAR(MAX)
SET @s=''
SELECT @s=@s+','+quotename([Backup_Date])+'=MAX(CASE WHEN [Backup_Date]='+quotename([Backup_Date],'''')+' THEN [Backup_Duration] ELSE NULL END)'
FROM [msdb].[dbo].[JobLog] GROUP BY [Backup_Date] ORDER BY [Backup_Date]
PRINT @s
EXEC('SELECT [DB_Name] '+@s+' FROM [msdb].[dbo].[JobLog]
GROUP BY [DB_Name] ORDER BY [DB_Name]')

wps_clip_image-20380

(Figure6:做業執行時間)

 

五.主分區完整、差別還原(Primary Backup And Restore)

  既然作了上面主文件組的備份,固然咱們須要去測試這個主文件組的還原了,這樣才能夠當遇到問題能夠快速還原備份文件,達到還原數據的目的;

  接下來會在另一篇文章裏面專門講解;

 

六.參考文獻(References)

sp_update_schedule (Transact-SQL)

如何修改 SQL Server 代理主做業 (Transact-SQL)

bat實現文件字符串替換

Sqlcmd 使用

相關文章
相關標籤/搜索