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

  1. 本文所涉及的内容(Contents)
  2. 背景(Contexts)
  3. 案例分析(Case)
  4. 实现代码(SQL Codes)
  5. 主分区完整、差异还原(Primary Backup And Restore)
  6. 参考文献(References)

二.背景(Contexts)

  在我的数据库实例中,有很多下图所示的数据库,这些数据库的名称是有规律的,每个数据库包含的表都是相同的,其中2个表是类似流水记录的表,表的数据量会比较大,占用的空间有几十G到上百G不等,这2个表相对于其它的配置表来说是比较不重要的。

  现在有一个需求就是对数据库进行备份,允许丢失这两个表的数据,保留重要的配置表数据,你是否遇到过同样的问题呢?这个时候你会怎么做呢?你有什么方案呢?有什么方法可以快速备份这些数据库呢?

(Figure1:数据库列表)

阅读本文之前你可以先参考:SQL Server 批量完整备份

三.案例分析(Case)

  通过上面的描述,其中很重要的一点就是每个数据库中有2个大表,而且这些数据是不重要的,那么我们对这2个大表做表分区,把大数据放到其它文件组中,只留重要的配置表在主文件组(PRIMARY)中,接着就可以对主文件组进行备份,这样既满足了备份重要表数据,而且不会造成备份文件过大、占用磁盘空间、备份时间过长等问题。

  确定了方向之后我们接着考虑作业的问题,通过作业备份类似Figure1的数据库,有下面两种方案可供选择:

(Figure2:作业列表)

(Figure3:作业列表)

  Figure2是一个方案,这些作业是可以自动化创建,但是会用到批处理,代码会复杂一点,唯一的缺点就是当新创建了数据库,是无法自动备份的(不过可以通过专门创建一个监控数据库的新建、删除状态的Job来解决这个问题)详情请参考:SQL Server 批量主分区备份(Multiple Jobs)

  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\目录下创建如下图所示的文件夹:

(Figure4:创建的文件夹)

(二) 对备份的维护,我希望可以了解到所有数据库的备份情况,所以下面创建2个维护表:[JobLog]和[ErrorLog],这两个表用于记录作业的执行情况,通过这两个表,可以实现如Figure5、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 维护计划备份主分区),当是星期一的深夜的时候,我们做完整备份,如果是其它时候我们就做差异备份,具体是什么时候,这个就通过计划里面的时候来控制了(计划的执行时间为星期一、星期三、星期五,这就代表星期一深夜做了完整备份、星期三和星期五分别做了差异备份)。(备份实践可参考: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]')

(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]')

(Figure6:作业执行时间)

五.主分区完整、差异还原(Primary Backup And Restore)

  既然做了上面主文件组的备份,当然我们需要去测试这个主文件组的还原了,这样才可以当遇到问题可以快速还原备份文件,达到还原数据的目的;

  接下来会在另外一篇文章里面专门讲解;

六.参考文献(References)

sp_update_schedule (Transact-SQL)

如何修改 SQL Server 代理主作业 (Transact-SQL)

bat实现文件字符串替换

Sqlcmd 使用

SQL Server 批量主分区备份(One Job)的更多相关文章

  1. SQL Server 批量主分区备份(Multiple Jobs)

    一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 案例分析(Case) 方案一(Solution One) 方案二(Solution Two) ...

  2. SQL Server 批量完整备份

    一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 实现代码(SQL Codes) 实现方式一(One) 实现方式二(Two) 实现方式三(Thr ...

  3. SQL Server 批量创建作业(备份主分区)

    一. 需求背景 在我的数据库实例中,有很多类似下图所示的数据库,这些数据库的名称是有规律的,每个数据库包含的表都是相同的,其中2个表是类似流水记录的表,表的数据量会比较大,占用的空间有几十G到上百G不 ...

  4. SQL Server 维护计划实现数据库备份(Step by Step)(转)

    SQL Server 维护计划实现数据库备份(Step by Step) 一.前言 SQL Server 备份和还原全攻略,里面包括了通过SSMS操作还原各种备份文件的图形指导,SQL Server  ...

  5. SQL Server 维护计划实现数据库备份(Step by Step)

    转自:http://www.cnblogs.com/gaizai/archive/2011/11/18/2254445.html 一.前言 SQL Server 备份和还原全攻略,里面包括了通过SSM ...

  6. SQL Server如何提高数据库备份的速度

    对于一个数据库完整备份来说,备份的速度很大程度上取决于下面两个因素:读磁盘数据.日志文件的吞吐量,写磁盘数据文件的吞吐量. 下图是备份过程中磁盘的变化情况: 读吞吐量 读吞吐量的大小取决于磁盘读取数据 ...

  7. SQL Server数据库定时自动备份

    SQL Server 数据库定时自动备份[转]   在SQL Server中出于数据安全的考虑,所以需要定期的备份数据库.而备份数据库一般又是在凌晨时间基本没有数据库操作的时候进行,所以我们不可能要求 ...

  8. SQL Server 维护计划实现数据库备份(策略实战)

    一.背景 之前写过一篇关于备份的文章:SQL Server 维护计划实现数据库备份,上面文章使用完整备份和差异备份基本上能解决数据库备份的问题,但是为了保障数据更加安全,我们需要再次完善我们的备份计划 ...

  9. 如何修改 SQL Server 代理主作业 (Transact-SQL)

    本主题介绍了如何使用存储过程修改 Microsoft SQL Server 代理主作业. 更改作业定义计划的详细信息 1.       执行 sp_update_schedule. 在作业中添加.更改 ...

随机推荐

  1. jQuery实践-网页版2048小游戏

    ▓▓▓▓▓▓ 大致介绍 看了一个实现网页版2048小游戏的视频,觉得能做出自己以前喜欢玩的小游戏很有意思便自己动手试了试,真正的验证了这句话-不要以为你以为的就是你以为的,看视频时觉得看懂了,会写了, ...

  2. 在PowerShell中使用curl(Invoke-WebRequest)

    前言 习惯了windows的界面模式就很难转去命令行,甚至以命令行发家的git也涌现出各种界面tool.然而命令行真的会比界面快的多,如果你是一个码农. situation:接到需求分析bug,需要访 ...

  3. 在离线环境中发布.NET Core至Windows Server 2008

    在离线环境中发布.NET Core至Windows Server 2008 0x00 写在开始 之前一篇博客中写了在离线环境中使用.NET Core,之后一边学习一边写了一些页面作为测试,现在打算发布 ...

  4. 让姑姑不再划拳 码农也要有原则 : SOLID via C#

    “姑娘,别这样.我们是有原则的.” “一个有原则的程序猿是不会写出 “摧毁地球” 这样的程序的,他们会写一个函数叫 “摧毁行星”而把地球当一个参数传进去.” “对,是时候和那些只会滚键盘的麻瓜不同了, ...

  5. 小白解决CENTOS7错误:Cannot find a valid baseurl for repo: base/7/x86_6

    刚入手的MacBook想着学点东西,本汪还是决定玩玩CentOS服务器,安装好了VirtualBox + CentOS. 打开一看,懵逼了!命令行! 行吧,先装个图形界面: $sudo yum gro ...

  6. SQLServer事务同步下如何收缩日志

    事务同步是SQLServer做读写分离的一种常用的方式. 随着业务数据的不断增长,数据库积攒了大量的日志,为了腾出硬盘空间,需要对数据库日志进行清理 订阅数据库的日志清理 因为订阅数据库所有的数据都来 ...

  7. HTML中上传与读取图片或文件(input file)----在路上(25)

    input file相关知识简例 在此介绍的input file相关知识为: 上传照片及文件,其中包括单次上传.批量上传.删除照片.增加照片.读取图片.对上传的图片或文件的判断,比如限制图片的张数.限 ...

  8. 前端学HTTP之重定向和负载均衡

    前面的话 HTTP并不是独自运行在网上的.很多协议都会在HTTP报文的传输过程中对其数据进行管理.HTTP只关心旅程的端点(发送者和接收者),但在包含有镜像服务器.Web代理和缓存的网络世界中,HTT ...

  9. 了不起的 nodejs-TwitterWeb 案例 bug 解决

    了不起的nodejs算是一本不错的入门书,不过书中个别案例存在bug,按照书中源码无法做出和书中相同效果,原本兴奋的心情掺杂着些许失落. 现在我们看一下第七章HTTP,一个Twitter Web客户端 ...

  10. git-2.10.2-64-bit介绍&&git下载&&git安装教程

    Git介绍 分布式:Git系统是一个分布式的系统,是用来保存工程源代码历史状态的命令行工具. 保存点:Git的保存点可以追踪源码中的文件, 并能得到某一个时间点上的整个工程项目的状态:可以在该保存点将 ...