目的:1.通用易于移植的备份方案。

2.易于监控备份情况。

3.方便选择不同组合备份方案。

下面先贴上说明:具体能实现的方案说明参见说明文档。




1. 备份方案参数说明 
2.  
3.  @Bakdbname Nvarchar(100)         --备份数据库名 
4. ,@BAKFILE NVARCHAR(100)       --备份集文件路径 
5. ,@ismirror int        =0
6. ,@BAKMIRFILE NVARCHAR(100) =NULL    --镜像备份集文件路径,默认是null 
7.                                --一般设置网络路径例如'\\192.168.6.100\sqlbak\' 
8. ,@devtype varchar(20) ='DISK'       --备份设备默认'disk' 
9. ,@D_EXP_DATE INT      =28
10. ,@I_EXP_DATE INT      =7
11. ,@iit INT             =2
12. ,@DbakBtime int       =3--完整或者差异备份开始时间点 默认 3点 
13. ,@DbakEtime int       =7--完整或者差异备份结束时间点 默认 7点 
14.  
15.  
16. D备份为完整备份 
17. I备份为差异备份 
18. L备份为日志备份 
19. --  参数说明 
20.  
21. --1.备份以最近的该库的D备份作为集合的起点,每个I和D备份为一个备份分块起点并设置每个分块备份的过期时间为 创建时间+@I_EXP_DATE。 
22.  
23. --2.当备份分块个数为 @D_EXP_DATE INT/@I_EXP_DATE 个个数的时候且最后的备份分块已经过期,则开始自动切到下一个完整备份集进行备份作业。如果已经是最大的备份集,则从头第一个备份集开始做备份作业 
24.  
25. --3.参数设置上需要注意 
26. >=@I_EXP_DATE 
27. >0 @I_EXP_DATE>=0 
28. >=1  代表需要最少保留的历史备份集合为@iit-1个最多设置999个! 
29.      d.@ismirror ,@BAKMIRFILE 
30.      @ismirror 确定是否使用镜像备份集为主备份集做一个镜像,如果为1则做, 
31.      当@ismirror为1的时候@bakmirfile镜像备份集的存放路径(可以是网络路径)参数    一定不能为NULL切需要保证可用! 
32.      
33.   程序利用备份参数设置来实现不同的备份方案! 
34. 设置的@D_EXP_DATE 为一个D备份开始的整体的备份集有效期间隔 
35.       @I_EXP_DATE为单个D和单个I备份的备份块有效期间隔 
36. 例如 @I_EXP_DATE=7则代表 从D开始算,每7天需要做一个I备份知道 D备份个数+I备份个数达到@D_EXP_DATE /@I_EXP_DATE(除法使用向上取整)个,且最后的备份区块也过期,则会自动轮换到下一个备份集做D备份。 
37. 在没有过期的这段时间间隔里,如果执行作业将会进行L备份! 
38.    
39. 4.举例来说: 
40.    
41.   @D_EXP_DATE ,@I_EXP_DATE,@iit 三个参数将涉及到备份策略下面举例说明。 
42.    
43.   支持三种备份方案 
44.   1.方案为 D+I+L 
45.   每28天做一次D备份 
46.   每7天做一次I备份 
47.   其它时间每小时做一次L备份 
48.   至少保持一个历史的备份集(既保持最最少28最多56天的历史备份记录) 
49.    
50.    
51.   参数设置如下: 
52. D_EXP_DATE=28
53. I_EXP_DATE=7
54. iit=2
55. >=28/7=4
56.  
57. 用户可以定义@DbakBtime ,@DbakEtime 起止时间点来确定做D和I备份的时间范围。例如值允许系统 不是很忙得晚上2点到3点之间做等 
58.    
59.    
60.    
61.   2.方案为 D+L 
62.   每7天做一次D备份 
63.   每小时做L备份 
64.   参数设置如下: 
65. D_EXP_DATE=7
66. I_EXP_DATE=7
67. >=7/7=1
68.   这样就达到了 D+L的备份策略 
69.    
70.    
71.   3.方案为 D 
72.   每天做一个D 
73.    
74. D_EXP_DATE=1
75. I_EXP_DATE=1
76.    
77. >=1/11=1 且最后的I备份或者D备份也已经过期的情况下,则会进行下一个备份集的备份操作,而保留之前这个完全饱和的备份集! 
78.   这样就达到了只做 D的备份策略 
79.    
80.    
81.   如果要更细分的 例如 D备份的时间间隔不是以天为单位 对大型数据库意义不大也不是很现实!所有 备份作业时间间隔都是以天作为单位 
82.  
83.    
84.   4.方案为 D+I 
85.    
86.    
87.   每天10天一个D备份 
88.   每1天一个I备份 
89.    
90.   参数如下 
91. D_EXP_DATE=10
92. I_EXP_DATE=1
93.    
94. >=10/11=1 且最后的I备份或者D备份也已经过期的情况下,则会进行下一个备份集的备份操作,而保留之前这个完全饱和的备份集! 
95.  这样就实现了D+I备份的备份策略! 
96.    
97.    
98.  
99. 注释 D备份为完整备份 
100.      I备份为差异备份 
101.      L备份为日志备份 
102.  
103.  
104. 该备份任务作业优点如下: 
105.     快速部署提供便利,只需要在master中建立对应存储过程即可 
106.     灵活方便,随意设置备份集个数,以及每个备份集的备份文件有效期天数,通过不同参数的设置即可实现各种不同需求的备份方案组合 
107.     自动覆盖过去备份集,省去对过期备份集的额外处理 
108.     提供镜像备份集,将备份同时放到两个地方,以防备份出现丢失等意外 
109.     提供简单快捷的备份任务监控语句,通过语句即可轻松监控每次备份任务的运行情况 
110. 例如 
111. 该脚本注意事项: 
112.     如果设置了多个定时任务,一定要将每个定时任务执行的时间错开,目前的机制是要使用到备份设备,每次备份会自动生成,所以防止互相干扰。如果放到一个定时任务中则可以一起运行。 
113.     如果要监控备份执行情况,请运行“备份监控语句”查看每个备份的执行情况!

错误代码含义:

0:执行正常! 11:首次完整备份时间段不合法! 12:备份作业执行异常! 13:镜像备份集参数配置未合格!

 

贴上使用方式的存储过程代码:

 




1. USE [msdb] 
2. GO 
3.  
4. /****** Object:  StoredProcedure [dbo].[USP_Bak_Sche]    Script Date: 2012/12/26 11:24:33 ******/ 
5. /*作者:泥 巴                ******/ 
6. /*日期:20130322         ******/ 
7. SET ANSI_NULLS ON
8. GO 
9.  
10. SET QUOTED_IDENTIFIER ON
11. GO 
12.  
13. CREATE
14. ( 
15. --备份数据库名
16. ,@BAKFILE NVARCHAR(100)       --备份集文件路径
17. ,@ismirror int        =0       --是否建立镜像备份集,默认为0不建立
18. ,@BAKMIRFILE NVARCHAR(100) =NULL    --镜像备份集文件路径,默认是null
19. ,@devtype varchar(20) ='DISK'       --默认'disk'
20. ,@D_EXP_DATE INT      =28       --备份集过期时间单位 (天) 默认 28天 
21. ,@I_EXP_DATE INT      =7       --差异和完整备份过期时间单位(天) 默认  7天
22. ,@iit INT             =2        --备份集数目用于交替备份到同备份集 默认2
23. ,@DbakBtime int       =3--完整或者差异备份开始时间点 默认 3点
24. ,@DbakEtime int       =7--完整或者差异备份结束时间点 默认 7点
25.  
26.  
27. ) 
28. AS
29. BEGIN
30.  
31. if @ismirror=1 begin
32. if @BAKMIRFILE is null begin
33. print N'用户选择开启镜像备份集,但是镜像备份路径参数@bakmirfile不能为NULL!'
34. print N'注意:中途更改这个参数@ismirror会自动在每次做新的备份集的时候才会生效。'
35. return
36. end
37. end
38.  
39. --参数校正
40.  
41. IF @D_EXP_DATE<=0 
42. BEGIN
43.  
44. SET @D_EXP_DATE=(CASE WHEN @D_EXP_DATE<=0 THEN 1 ELSE @D_EXP_DATE END) 
45. PRINT N'备份集参数过期设置@d_exp_date 不能小于1,系统自动修正为1!'
46.  
47. END
48.  
49. IF @D_EXP_DATE<@I_EXP_DATE 
50.  
51. BEGIN
52.  
53. SET
54. PRINT N'备份块过期值应该小于或等于备份集过期值,参数已经修正为相等!'
55.  
56. END
57.  
58. --set @allbgname=''
59. declare @it int                 --循环种子
60. ,@baklogicname varchar(20)      --备份集逻辑名
61. ,@bakfilename varchar(100)      --备份集路径文件名
62. ,@MIRbaklogicname varchar(20)   --镜像备份集逻辑名
63. ,@MIRbakfilename varchar(100)   --镜像备份集路径文件名
64. ,@bacname Nvarchar(100)         --备份名称
65. ,@bacmeidaname Nvarchar(100)    --备份媒体名称
66. ,@sql   Nvarchar(2000) 
67. set @bacname=@Bakdbname+'_BAK'
68. set @bacmeidaname=@Bakdbname+'_MEDIA'
69. --建立所需要的备份集合
70. set
71. while @it<=@iit 
72. begin
73. set @baklogicname='My_bak'+ convert(varchar(10),@it) 
74. set @bakfilename=@BAKFILE+@bakdbname+'_BAK'+ convert(varchar(10),@it)+'.BAK'
75. IF NOT EXISTS(SELECT * FROM sys.backup_devices WHERE name=@baklogicname) 
76. BEGIN
77. exec
78. end
79. IF @ISMIRROR=1 
80. BEGIN
81. set @MIRbaklogicname='MIRROR_'+@baklogicname 
82. set @MIRbakfilename=@BAKMIRFILE+'MIRROR_'+@bakdbname+'_BAK'+ convert(varchar(10),@it)+'.BAK'
83. IF NOT EXISTS(SELECT 1 FROM sys.backup_devices WHERE name=@MIRbaklogicname) 
84. BEGIN
85. exec
86.  
87. END
88. END
89.  
90. set
91.  
92. end
93.  
94. --建立当前活动备份集的临时表
95.  
96.  
97.  
98. ;WITH
99. AS
100. ( 
101. select A.database_name,A.backup_set_id,position, type,first_lsn,last_lsn,checkpoint_lsn,database_backup_lsn,isnull(datediff(d,backup_start_date,expiration_date),0) exp_day from
102. join (select database_name,MAX(backup_set_id) backup_set_id from
103. where database_name=@Bakdbname and type='D'
104. group by
105. on a.backup_set_id=b.backup_set_id and
106. --找出同组的备份组集合所有
107. union all
108. select A.database_name,A.backup_set_id,a.position, a.type,a.first_lsn,a.last_lsn,a.checkpoint_lsn,a.database_backup_lsn,isnull(datediff(d,backup_start_date,expiration_date),0) exp_day from
109. join
110. select A.database_name,A.backup_set_id,position, A.type,first_lsn,last_lsn,checkpoint_lsn,database_backup_lsn,isnull(datediff(d,backup_start_date,expiration_date),0) exp_day from
111. join (select database_name,MAX(backup_set_id) backup_set_id from
112. where database_name=@Bakdbname and type='D'
113. group by
114. on a.backup_set_id=b.backup_set_id and
115. ) b 
116. on a.database_backup_lsn=b.checkpoint_lsn AND
117. where a.type <>'D'
118.  
119. ) 
120. select  bf.*,cf.exp_day into
121. from
122. join
123. (select
124. bcs.backup_set_id, 
125. bcs.position, 
126. [BACK_TYPE]=bcs.type, 
127. [bacname]=bcs.name, 
128. bcs.database_name, 
129. [medianame]=bms.name, 
130. [BACdevicename]=bmf.logical_device_name, 
131. [dev_type]=bmf.device_type, 
132. [PHYS_DEVICE_NAME]=bmf.physical_device_name, 
133. bcs.expiration_date, 
134. --bcs.backup_set_uuid,
135. bcs.database_backup_lsn, 
136. bcs.first_lsn, 
137. bcs.last_lsn, 
138. bcs.checkpoint_lsn, 
139. --bcs.database_creation_date,
140. bcs.backup_start_date, 
141. bcs.backup_finish_date, 
142. [size/M]=bcs.compressed_backup_size/1024/1024 
143. from
144. join
145. join
146. on
147. on
148. on
149. where BF.database_name=@Bakdbname and BACdevicename in
150. select name from
151. where name like '%My_bak%'
152. ) 
153. order by
154.  
155. --初始备份集参数
156. set
157. --判断需要备份的数据库是否有D备份在所有备份集中
158. --
159. IF  exists( 
160. select * from #tempbak where BACK_TYPE='D'
161. ) 
162. --有D备份存在的情况
163. begin
164. --用历史备份集参数来重新赋值,以保证一个没有完全饱和的备份集参数都是一致的
165.  
166. select @it=SUBSTRING(BACdevicename,7,3) from #tempbak  where back_type='D' and BACdevicename like 'My_bak%'
167. select @baklogicname=BACDEVICENAME FROM #TEMPBAK WHERE BACK_TYPE='D' and BACdevicename = 'My_bak'+convert(varchar(10),@it) 
168. select @MIRbaklogicname='MIRROR_'+@baklogicname 
169. select @bacmeidaname=MEDIANAME FROM #TEMPBAK WHERE BACK_TYPE='D' and BACdevicename = 'My_bak'+convert(varchar(10),@it) 
170. SELEct @bacname=bacname FROM #TEMPBAK WHERE BACK_TYPE='D' and BACdevicename = 'My_bak'+convert(varchar(10),@it) 
171. --set @baklogicname='My_bak'+ convert(varchar(10),@it)
172. SELECT @bakfilename=[PHYS_DEVICE_NAME]  from #tempbak  where back_type='D' and BACdevicename = 'My_bak'+convert(varchar(10),@it) 
173. select @MIRbaklogicname= [BACdevicename] from #tempbak where back_type='D' and BACdevicename = 'MIRROR_My_bak'+convert(varchar(10),@it) 
174. select @MIRbakfilename= [PHYS_DEVICE_NAME]  from #tempbak  where back_type='D' and BACdevicename = 'MIRROR_My_bak'+convert(varchar(10),@it) 
175.  
176. --判断历史D备中如果没有MIRROR备份集那么把标签自动设置为0
177.  
178. --如果
179.  
180.  
181. IF datepart(hh,GETDATE()) >=@DbakBtime and
182. --在3点到7点之间
183. begin
184. --判断最后的差异或者D备是否已经过期
185. select CONVERT(VARCHAR(8),MAX(expiration_date),112) exp_day FROM #TEMPBAK)<=CONVERT(VARCHAR(8),GETDATE(),112) 
186. --备份块已经过期
187. begin
188. --检查D+I备的个数是否已经饱和
189. select COUNT(1) from #tempbak  where back_type in ('D','I') and BACdevicename like 'My_bak%')>= ceiling(convert(numeric(19,2),@D_EXP_DATE)/convert(numeric(19,2),case  when @I_EXP_DATE<=0 then @D_EXP_DATE else @I_EXP_DATE end)) 
190. --备份分块已经饱和
191. begin
192.             IF @it<@iit 
193. --备份集还没有达到最大
194. begin
195. --设置备份集参数为下一个
196. select @it=SUBSTRING(BACdevicename,7,3) from #tempbak  where back_type='D' and BACdevicename like 'My_bak%'
197. set
198. GOTO
199. end
200.              
201. else
202. --备份集已经达到最大
203. begin
204. --设置备份集参数为初始第一个
205. set
206. GOTO
207. end
208.              
209. end
210. --备份集没有饱和
211. else
212. begin
213. goto
214. end
215. end
216.      
217. ELSE
218. --备份分块没有过期
219. begin
220. goto
221. end
222.  
223. end
224. --当前时间不在完整和差异备份时间段之间
225. else begin
226. --做L备份
227. goto
228. end
229. end
230. --在没有D备份存在的情况
231. else begin
232.      
233. set
234. --当前时间在完整和差异备份时间段之间
235. IF datepart(hh,GETDATE()) >=@DbakBtime and
236. begin
237. GOTO
238. end
239. --当前时间不在完整和差异备份时间段之间
240. else begin
241.  
242. '当前的备份集下还没有过任何D备份,且不在做D备份时间段,请选择正确时间段运行以便首次建立D备份!请确认设置的时间段合法!'
243. return
244.      
245. end
246.  
247. end
248.  
249.  
250.  
251. --第创建使用fomat创建媒体集和备份集以及镜像备份集
252.  
253. Dbak: 
254. begin
255. set @baklogicname='My_bak'+ convert(varchar(10),@it) 
256. SET @MIRbaklogicname='MIRROR_'+@baklogicname 
257. set @bacname=@Bakdbname+'_BAK'
258. set @bacmeidaname=@Bakdbname+'_MEDIA'
259. set @bakfilename=@BAKFILE+@bakdbname+'_BAK'+ convert(varchar(10),@it)+'.BAK'
260. set @MIRbakfilename=@BAKMIRFILE+'MIRROR_'+@bakdbname+'_BAK'+ convert(varchar(10),@it)+'.BAK'
261. --重建基础备份设备
262. SELECT 1 FROM sys.backup_devices WHERE name
263. begin
264. exec
265. exec
266. end else exec
267. --重建镜像备份设备
268.             IF @ismirror=1  
269. BEGIN
270. SELECT 1 FROM sys.backup_devices WHERE name
271. begin
272. exec
273. exec
274. end else exec
275. END
276.              
277. IF @ismirror=1  
278. begin
279. set
280. BACKUP DATABASE ['+@Bakdbname+'] TO '+@baklogicname+'
281. MIRROR TO '+@MIRbaklogicname+'
282. WITH  RETAINDAYS = '+convert(varchar(10),@I_EXP_DATE)+', FORMAT,  
283. INIT,  MEDIANAME =  '''+@bacmeidaname+''', NAME = '''+@bacname+''', 
284. SKIP, NOREWIND, NOUNLOAD, COMPRESSION,  STATS = 10 
285. ' 
286. drop table
287. print @sql 
288. EXEC
289. IF @@ERROR<>0 GOTO
290. print N'完整备份成功带镜像!'
291. return
292. end
293. else begin
294. set
295. BACKUP DATABASE ['+@Bakdbname+'] TO '+@baklogicname+'
296. WITH  RETAINDAYS = '+convert(varchar(10),@I_EXP_DATE)+', FORMAT,  
297. INIT,  MEDIANAME =  '''+@bacmeidaname+''', NAME = '''+@bacname+''', 
298. SKIP, NOREWIND, NOUNLOAD, COMPRESSION,  STATS = 10 
299. ' 
300. drop table
301. print @sql 
302. EXEC
303. IF @@ERROR<>0 GOTO
304. print N'完整备份成功无镜像!'
305. return
306. end
307.      
308. end
309. --创建差异备份
310. Ibak: 
311. begin
312. --重建基础备份设备
313. SELECT 1 FROM sys.backup_devices WHERE name
314. begin
315. exec
316. exec
317. end else exec
318. --重建镜像备份设备
319.             IF @ismirror=1  
320. BEGIN
321. SELECT 1 FROM sys.backup_devices WHERE name
322. begin
323. exec
324. exec
325. end else exec
326. END
327. select @I_EXP_DATE=exp_day FROM #TEMPBAK WHERE BACK_TYPE='D' and BACdevicename = 'My_bak'+convert(varchar(10),@it) 
328. --判断历史D备份中的是否也包含了MIRROR备份,如果没有则修正@ismirror为0
329. SELECT 1 from #TEMPBAK WHERE BACK_TYPE='D' and BACdevicename = 'MIRROR_My_bak'+convert(varchar(10),@it)) 
330. begin
331. SET
332. select @MIRbaklogicname=BACDEVICENAME FROM #TEMPBAK WHERE BACK_TYPE='D' and BACdevicename = 'MIRROR_My_bak'+convert(varchar(10),@it) 
333. end
334. else set
335.  
336. IF @ismirror=1 BEGIN
337. set
338. BACKUP DATABASE ['+@Bakdbname+'] TO '+@baklogicname+'
339. MIRROR TO '+@MIRbaklogicname+'
340. WITH  DIFFERENTIAL ,RETAINDAYS = '+convert(varchar(10),@I_EXP_DATE)+'
341. NOINIT,  MEDIANAME = '''+@bacmeidaname+''',  NAME = '''+@bacname+''',  
342. NOSKIP, NOREWIND, NOUNLOAD, COMPRESSION,  STATS = 10 
343. ' 
344.  
345. drop table
346. print @sql 
347. EXEC
348. IF @@ERROR<>0 GOTO
349. print N'差异备份成功带镜像!'
350. return
351. END
352. ELSE BEGIN
353. set
354. BACKUP DATABASE ['+@Bakdbname+'] TO '+@baklogicname+'
355. WITH  DIFFERENTIAL ,RETAINDAYS = '+convert(varchar(10),@I_EXP_DATE)+'
356. NOINIT,  MEDIANAME = '''+@bacmeidaname+''',  NAME = '''+@bacname+''',  
357. NOSKIP, NOREWIND, NOUNLOAD, COMPRESSION,  STATS = 10 
358. ' 
359. drop table
360. print @sql 
361. EXEC
362. IF @@ERROR<>0 GOTO
363. print N'差异备份成功无镜像!'
364. return
365. END
366. end
367. --创建日志备份
368.  
369. Lbak: 
370. begin
371.  
372. --重建基础备份设备
373. SELECT 1 FROM sys.backup_devices WHERE name
374. begin
375. exec
376. exec
377. end else exec
378. --重建镜像备份设备
379.             IF @ismirror=1  
380. BEGIN
381. SELECT 1 FROM sys.backup_devices WHERE name
382. begin
383. exec
384. exec
385. end else exec
386. END
387.              
388. select @I_EXP_DATE=exp_day FROM #TEMPBAK WHERE BACK_TYPE='D' and BACdevicename = 'My_bak'+convert(varchar(10),@it) 
389. --判断历史D备份中的是否也包含了MIRROR备份,如果没有则修正@ismirror为0
390.  
391. SELECT 1 from #TEMPBAK WHERE BACK_TYPE='D' and BACdevicename = 'MIRROR_My_bak'+convert(varchar(10),@it)) 
392. begin
393. SET
394. select @MIRbaklogicname=BACDEVICENAME FROM #TEMPBAK WHERE BACK_TYPE='D' and BACdevicename = 'MIRROR_My_bak'+convert(varchar(10),@it) 
395. end
396. else set
397.  
398.  
399. IF @ismirror=1 
400. --参数需要镜像备份集
401. BEGIN
402. select @I_EXP_DATE=exp_day FROM #TEMPBAK WHERE BACK_TYPE='D' and BACdevicename = 'My_bak'+convert(varchar(10),@it) 
403. set
404. BACKUP LOG ['+@Bakdbname+'] TO  '+@baklogicname+'
405. MIRROR TO '+@MIRbaklogicname+'
406. WITH
407. NOINIT,  MEDIANAME = '''+@bacmeidaname+''',  NAME = '''+@bacname+''',  
408. NOSKIP, NOREWIND, NOUNLOAD, COMPRESSION, STATS = 10' 
409.  
410. drop table
411. print @sql 
412. EXEC
413. IF @@ERROR<>0 GOTO
414. print N'日志备份成功带镜像!'
415. return
416. END
417.  
418. --参数设置不需要镜像备份集
419. ELSE BEGIN
420.  
421. set
422. BACKUP LOG ['+@Bakdbname+'] TO  '+@baklogicname+'
423. WITH
424. NOINIT,  MEDIANAME = '''+@bacmeidaname+''',  NAME = '''+@bacname+''',  
425. NOSKIP, NOREWIND, NOUNLOAD, COMPRESSION, STATS = 10' 
426.  
427. drop table
428. print @sql 
429. EXEC
430. IF @@ERROR<>0 GOTO
431. print N'日志备份成功无镜像!'
432. return
433.  
434. END
435. end
436.  
437. ----备份日志尾部
438. --BACKUP LOG [ReportServer] TO SH_TC_BAK WITH  NO_TRUNCATE , 
439. --NOFORMAT, NOINIT,MEDIANAME=N'SH_TC_BAKMEDIA', NAME = N'SH_TC_TRUNLOG', 
440. --NOSKIP, NOREWIND, NOUNLOAD,  NORECOVERY ,  STATS = 10
441.  
442. ERR: 
443. BEGIN
444.  
445. PRINT N'备份作业异常!请检查'
446. return
447. END
448.  
449.  
450. END
451.  
452.  
453. GO
1. USE [msdb] 
2. GO 
3.  
4. /****** Object:  StoredProcedure [dbo].[USP_Bak_Sche]    Script Date: 2012/12/26 11:24:33 ******/ 
5. /*作者:泥 巴                ******/ 
6. /*日期:20130322         ******/ 
7. SET ANSI_NULLS ON
8. GO 
9.  
10. SET QUOTED_IDENTIFIER ON
11. GO 
12.  
13. CREATE
14. ( 
15. --备份数据库名
16. ,@BAKFILE NVARCHAR(100)       --备份集文件路径
17. ,@ismirror int        =0       --是否建立镜像备份集,默认为0不建立
18. ,@BAKMIRFILE NVARCHAR(100) =NULL    --镜像备份集文件路径,默认是null
19. ,@devtype varchar(20) ='DISK'       --默认'disk'
20. ,@D_EXP_DATE INT      =28       --备份集过期时间单位 (天) 默认 28天 
21. ,@I_EXP_DATE INT      =7       --差异和完整备份过期时间单位(天) 默认  7天
22. ,@iit INT             =2        --备份集数目用于交替备份到同备份集 默认2
23. ,@DbakBtime int       =3--完整或者差异备份开始时间点 默认 3点
24. ,@DbakEtime int       =7--完整或者差异备份结束时间点 默认 7点
25.  
26.  
27. ) 
28. AS
29. BEGIN
30.  
31. if @ismirror=1 begin
32. if @BAKMIRFILE is null begin
33. print N'用户选择开启镜像备份集,但是镜像备份路径参数@bakmirfile不能为NULL!'
34. print N'注意:中途更改这个参数@ismirror会自动在每次做新的备份集的时候才会生效。'
35. return
36. end
37. end
38.  
39. --参数校正
40.  
41. IF @D_EXP_DATE<=0 
42. BEGIN
43.  
44. SET @D_EXP_DATE=(CASE WHEN @D_EXP_DATE<=0 THEN 1 ELSE @D_EXP_DATE END) 
45. PRINT N'备份集参数过期设置@d_exp_date 不能小于1,系统自动修正为1!'
46.  
47. END
48.  
49. IF @D_EXP_DATE<@I_EXP_DATE 
50.  
51. BEGIN
52.  
53. SET
54. PRINT N'备份块过期值应该小于或等于备份集过期值,参数已经修正为相等!'
55.  
56. END
57.  
58. --set @allbgname=''
59. declare @it int                 --循环种子
60. ,@baklogicname varchar(20)      --备份集逻辑名
61. ,@bakfilename varchar(100)      --备份集路径文件名
62. ,@MIRbaklogicname varchar(20)   --镜像备份集逻辑名
63. ,@MIRbakfilename varchar(100)   --镜像备份集路径文件名
64. ,@bacname Nvarchar(100)         --备份名称
65. ,@bacmeidaname Nvarchar(100)    --备份媒体名称
66. ,@sql   Nvarchar(2000) 
67. set @bacname=@Bakdbname+'_BAK'
68. set @bacmeidaname=@Bakdbname+'_MEDIA'
69. --建立所需要的备份集合
70. set
71. while @it<=@iit 
72. begin
73. set @baklogicname='My_bak'+ convert(varchar(10),@it) 
74. set @bakfilename=@BAKFILE+@bakdbname+'_BAK'+ convert(varchar(10),@it)+'.BAK'
75. IF NOT EXISTS(SELECT * FROM sys.backup_devices WHERE name=@baklogicname) 
76. BEGIN
77. exec
78. end
79. IF @ISMIRROR=1 
80. BEGIN
81. set @MIRbaklogicname='MIRROR_'+@baklogicname 
82. set @MIRbakfilename=@BAKMIRFILE+'MIRROR_'+@bakdbname+'_BAK'+ convert(varchar(10),@it)+'.BAK'
83. IF NOT EXISTS(SELECT 1 FROM sys.backup_devices WHERE name=@MIRbaklogicname) 
84. BEGIN
85. exec
86.  
87. END
88. END
89.  
90. set
91.  
92. end
93.  
94. --建立当前活动备份集的临时表
95.  
96.  
97.  
98. ;WITH
99. AS
100. ( 
101. select A.database_name,A.backup_set_id,position, type,first_lsn,last_lsn,checkpoint_lsn,database_backup_lsn,isnull(datediff(d,backup_start_date,expiration_date),0) exp_day from
102. join (select database_name,MAX(backup_set_id) backup_set_id from
103. where database_name=@Bakdbname and type='D'
104. group by
105. on a.backup_set_id=b.backup_set_id and
106. --找出同组的备份组集合所有
107. union all
108. select A.database_name,A.backup_set_id,a.position, a.type,a.first_lsn,a.last_lsn,a.checkpoint_lsn,a.database_backup_lsn,isnull(datediff(d,backup_start_date,expiration_date),0) exp_day from
109. join
110. select A.database_name,A.backup_set_id,position, A.type,first_lsn,last_lsn,checkpoint_lsn,database_backup_lsn,isnull(datediff(d,backup_start_date,expiration_date),0) exp_day from
111. join (select database_name,MAX(backup_set_id) backup_set_id from
112. where database_name=@Bakdbname and type='D'
113. group by
114. on a.backup_set_id=b.backup_set_id and
115. ) b 
116. on a.database_backup_lsn=b.checkpoint_lsn AND
117. where a.type <>'D'
118.  
119. ) 
120. select  bf.*,cf.exp_day into
121. from
122. join
123. (select
124. bcs.backup_set_id, 
125. bcs.position, 
126. [BACK_TYPE]=bcs.type, 
127. [bacname]=bcs.name, 
128. bcs.database_name, 
129. [medianame]=bms.name, 
130. [BACdevicename]=bmf.logical_device_name, 
131. [dev_type]=bmf.device_type, 
132. [PHYS_DEVICE_NAME]=bmf.physical_device_name, 
133. bcs.expiration_date, 
134. --bcs.backup_set_uuid,
135. bcs.database_backup_lsn, 
136. bcs.first_lsn, 
137. bcs.last_lsn, 
138. bcs.checkpoint_lsn, 
139. --bcs.database_creation_date,
140. bcs.backup_start_date, 
141. bcs.backup_finish_date, 
142. [size/M]=bcs.compressed_backup_size/1024/1024 
143. from
144. join
145. join
146. on
147. on
148. on
149. where BF.database_name=@Bakdbname and BACdevicename in
150. select name from
151. where name like '%My_bak%'
152. ) 
153. order by
154.  
155. --初始备份集参数
156. set
157. --判断需要备份的数据库是否有D备份在所有备份集中
158. --
159. IF  exists( 
160. select * from #tempbak where BACK_TYPE='D'
161. ) 
162. --有D备份存在的情况
163. begin
164. --用历史备份集参数来重新赋值,以保证一个没有完全饱和的备份集参数都是一致的
165.  
166. select @it=SUBSTRING(BACdevicename,7,3) from #tempbak  where back_type='D' and BACdevicename like 'My_bak%'
167. select @baklogicname=BACDEVICENAME FROM #TEMPBAK WHERE BACK_TYPE='D' and BACdevicename = 'My_bak'+convert(varchar(10),@it) 
168. select @MIRbaklogicname='MIRROR_'+@baklogicname 
169. select @bacmeidaname=MEDIANAME FROM #TEMPBAK WHERE BACK_TYPE='D' and BACdevicename = 'My_bak'+convert(varchar(10),@it) 
170. SELEct @bacname=bacname FROM #TEMPBAK WHERE BACK_TYPE='D' and BACdevicename = 'My_bak'+convert(varchar(10),@it) 
171. --set @baklogicname='My_bak'+ convert(varchar(10),@it)
172. SELECT @bakfilename=[PHYS_DEVICE_NAME]  from #tempbak  where back_type='D' and BACdevicename = 'My_bak'+convert(varchar(10),@it) 
173. select @MIRbaklogicname= [BACdevicename] from #tempbak where back_type='D' and BACdevicename = 'MIRROR_My_bak'+convert(varchar(10),@it) 
174. select @MIRbakfilename= [PHYS_DEVICE_NAME]  from #tempbak  where back_type='D' and BACdevicename = 'MIRROR_My_bak'+convert(varchar(10),@it) 
175.  
176. --判断历史D备中如果没有MIRROR备份集那么把标签自动设置为0
177.  
178. --如果
179.  
180.  
181. IF datepart(hh,GETDATE()) >=@DbakBtime and
182. --在3点到7点之间
183. begin
184. --判断最后的差异或者D备是否已经过期
185. select CONVERT(VARCHAR(8),MAX(expiration_date),112) exp_day FROM #TEMPBAK)<=CONVERT(VARCHAR(8),GETDATE(),112) 
186. --备份块已经过期
187. begin
188. --检查D+I备的个数是否已经饱和
189. select COUNT(1) from #tempbak  where back_type in ('D','I') and BACdevicename like 'My_bak%')>= ceiling(convert(numeric(19,2),@D_EXP_DATE)/convert(numeric(19,2),case  when @I_EXP_DATE<=0 then @D_EXP_DATE else @I_EXP_DATE end)) 
190. --备份分块已经饱和
191. begin
192.             IF @it<@iit 
193. --备份集还没有达到最大
194. begin
195. --设置备份集参数为下一个
196. select @it=SUBSTRING(BACdevicename,7,3) from #tempbak  where back_type='D' and BACdevicename like 'My_bak%'
197. set
198. GOTO
199. end
200.              
201. else
202. --备份集已经达到最大
203. begin
204. --设置备份集参数为初始第一个
205. set
206. GOTO
207. end
208.              
209. end
210. --备份集没有饱和
211. else
212. begin
213. goto
214. end
215. end
216.      
217. ELSE
218. --备份分块没有过期
219. begin
220. goto
221. end
222.  
223. end
224. --当前时间不在完整和差异备份时间段之间
225. else begin
226. --做L备份
227. goto
228. end
229. end
230. --在没有D备份存在的情况
231. else begin
232.      
233. set
234. --当前时间在完整和差异备份时间段之间
235. IF datepart(hh,GETDATE()) >=@DbakBtime and
236. begin
237. GOTO
238. end
239. --当前时间不在完整和差异备份时间段之间
240. else begin
241.  
242. '当前的备份集下还没有过任何D备份,且不在做D备份时间段,请选择正确时间段运行以便首次建立D备份!请确认设置的时间段合法!'
243. return
244.      
245. end
246.  
247. end
248.  
249.  
250.  
251. --第创建使用fomat创建媒体集和备份集以及镜像备份集
252.  
253. Dbak: 
254. begin
255. set @baklogicname='My_bak'+ convert(varchar(10),@it) 
256. SET @MIRbaklogicname='MIRROR_'+@baklogicname 
257. set @bacname=@Bakdbname+'_BAK'
258. set @bacmeidaname=@Bakdbname+'_MEDIA'
259. set @bakfilename=@BAKFILE+@bakdbname+'_BAK'+ convert(varchar(10),@it)+'.BAK'
260. set @MIRbakfilename=@BAKMIRFILE+'MIRROR_'+@bakdbname+'_BAK'+ convert(varchar(10),@it)+'.BAK'
261. --重建基础备份设备
262. SELECT 1 FROM sys.backup_devices WHERE name
263. begin
264. exec
265. exec
266. end else exec
267. --重建镜像备份设备
268.             IF @ismirror=1  
269. BEGIN
270. SELECT 1 FROM sys.backup_devices WHERE name
271. begin
272. exec
273. exec
274. end else exec
275. END
276.              
277. IF @ismirror=1  
278. begin
279. set
280. BACKUP DATABASE ['+@Bakdbname+'] TO '+@baklogicname+'
281. MIRROR TO '+@MIRbaklogicname+'
282. WITH  RETAINDAYS = '+convert(varchar(10),@I_EXP_DATE)+', FORMAT,  
283. INIT,  MEDIANAME =  '''+@bacmeidaname+''', NAME = '''+@bacname+''', 
284. SKIP, NOREWIND, NOUNLOAD, COMPRESSION,  STATS = 10 
285. ' 
286. drop table
287. print @sql 
288. EXEC
289. IF @@ERROR<>0 GOTO
290. print N'完整备份成功带镜像!'
291. return
292. end
293. else begin
294. set
295. BACKUP DATABASE ['+@Bakdbname+'] TO '+@baklogicname+'
296. WITH  RETAINDAYS = '+convert(varchar(10),@I_EXP_DATE)+', FORMAT,  
297. INIT,  MEDIANAME =  '''+@bacmeidaname+''', NAME = '''+@bacname+''', 
298. SKIP, NOREWIND, NOUNLOAD, COMPRESSION,  STATS = 10 
299. ' 
300. drop table
301. print @sql 
302. EXEC
303. IF @@ERROR<>0 GOTO
304. print N'完整备份成功无镜像!'
305. return
306. end
307.      
308. end
309. --创建差异备份
310. Ibak: 
311. begin
312. --重建基础备份设备
313. SELECT 1 FROM sys.backup_devices WHERE name
314. begin
315. exec
316. exec
317. end else exec
318. --重建镜像备份设备
319.             IF @ismirror=1  
320. BEGIN
321. SELECT 1 FROM sys.backup_devices WHERE name
322. begin
323. exec
324. exec
325. end else exec
326. END
327. select @I_EXP_DATE=exp_day FROM #TEMPBAK WHERE BACK_TYPE='D' and BACdevicename = 'My_bak'+convert(varchar(10),@it) 
328. --判断历史D备份中的是否也包含了MIRROR备份,如果没有则修正@ismirror为0
329. SELECT 1 from #TEMPBAK WHERE BACK_TYPE='D' and BACdevicename = 'MIRROR_My_bak'+convert(varchar(10),@it)) 
330. begin
331. SET
332. select @MIRbaklogicname=BACDEVICENAME FROM #TEMPBAK WHERE BACK_TYPE='D' and BACdevicename = 'MIRROR_My_bak'+convert(varchar(10),@it) 
333. end
334. else set
335.  
336. IF @ismirror=1 BEGIN
337. set
338. BACKUP DATABASE ['+@Bakdbname+'] TO '+@baklogicname+'
339. MIRROR TO '+@MIRbaklogicname+'
340. WITH  DIFFERENTIAL ,RETAINDAYS = '+convert(varchar(10),@I_EXP_DATE)+'
341. NOINIT,  MEDIANAME = '''+@bacmeidaname+''',  NAME = '''+@bacname+''',  
342. NOSKIP, NOREWIND, NOUNLOAD, COMPRESSION,  STATS = 10 
343. ' 
344.  
345. drop table
346. print @sql 
347. EXEC
348. IF @@ERROR<>0 GOTO
349. print N'差异备份成功带镜像!'
350. return
351. END
352. ELSE BEGIN
353. set
354. BACKUP DATABASE ['+@Bakdbname+'] TO '+@baklogicname+'
355. WITH  DIFFERENTIAL ,RETAINDAYS = '+convert(varchar(10),@I_EXP_DATE)+'
356. NOINIT,  MEDIANAME = '''+@bacmeidaname+''',  NAME = '''+@bacname+''',  
357. NOSKIP, NOREWIND, NOUNLOAD, COMPRESSION,  STATS = 10 
358. ' 
359. drop table
360. print @sql 
361. EXEC
362. IF @@ERROR<>0 GOTO
363. print N'差异备份成功无镜像!'
364. return
365. END
366. end
367. --创建日志备份
368.  
369. Lbak: 
370. begin
371.  
372. --重建基础备份设备
373. SELECT 1 FROM sys.backup_devices WHERE name
374. begin
375. exec
376. exec
377. end else exec
378. --重建镜像备份设备
379.             IF @ismirror=1  
380. BEGIN
381. SELECT 1 FROM sys.backup_devices WHERE name
382. begin
383. exec
384. exec
385. end else exec
386. END
387.              
388. select @I_EXP_DATE=exp_day FROM #TEMPBAK WHERE BACK_TYPE='D' and BACdevicename = 'My_bak'+convert(varchar(10),@it) 
389. --判断历史D备份中的是否也包含了MIRROR备份,如果没有则修正@ismirror为0
390.  
391. SELECT 1 from #TEMPBAK WHERE BACK_TYPE='D' and BACdevicename = 'MIRROR_My_bak'+convert(varchar(10),@it)) 
392. begin
393. SET
394. select @MIRbaklogicname=BACDEVICENAME FROM #TEMPBAK WHERE BACK_TYPE='D' and BACdevicename = 'MIRROR_My_bak'+convert(varchar(10),@it) 
395. end
396. else set
397.  
398.  
399. IF @ismirror=1 
400. --参数需要镜像备份集
401. BEGIN
402. select @I_EXP_DATE=exp_day FROM #TEMPBAK WHERE BACK_TYPE='D' and BACdevicename = 'My_bak'+convert(varchar(10),@it) 
403. set
404. BACKUP LOG ['+@Bakdbname+'] TO  '+@baklogicname+'
405. MIRROR TO '+@MIRbaklogicname+'
406. WITH
407. NOINIT,  MEDIANAME = '''+@bacmeidaname+''',  NAME = '''+@bacname+''',  
408. NOSKIP, NOREWIND, NOUNLOAD, COMPRESSION, STATS = 10' 
409.  
410. drop table
411. print @sql 
412. EXEC
413. IF @@ERROR<>0 GOTO
414. print N'日志备份成功带镜像!'
415. return
416. END
417.  
418. --参数设置不需要镜像备份集
419. ELSE BEGIN
420.  
421. set
422. BACKUP LOG ['+@Bakdbname+'] TO  '+@baklogicname+'
423. WITH
424. NOINIT,  MEDIANAME = '''+@bacmeidaname+''',  NAME = '''+@bacname+''',  
425. NOSKIP, NOREWIND, NOUNLOAD, COMPRESSION, STATS = 10' 
426.  
427. drop table
428. print @sql 
429. EXEC
430. IF @@ERROR<>0 GOTO
431. print N'日志备份成功无镜像!'
432. return
433.  
434. END
435. end
436.  
437. ----备份日志尾部
438. --BACKUP LOG [ReportServer] TO SH_TC_BAK WITH  NO_TRUNCATE , 
439. --NOFORMAT, NOINIT,MEDIANAME=N'SH_TC_BAKMEDIA', NAME = N'SH_TC_TRUNLOG', 
440. --NOSKIP, NOREWIND, NOUNLOAD,  NORECOVERY ,  STATS = 10
441.  
442. ERR: 
443. BEGIN
444.  
445. PRINT N'备份作业异常!请检查'
446. return
447. END
448.  
449.  
450. END
451.  
452.  
453. GO

调用方式:直接调用存储过程并按说明给出参数即可。

监控实现代码:




1. ;WITH
2. AS
3. ( 
4. select A.database_name,A.backup_set_id,position, type,first_lsn,last_lsn,checkpoint_lsn,database_backup_lsn,isnull(datediff(d,backup_start_date,expiration_date),0) exp_day from
5. join (select database_name,MAX(backup_set_id) backup_set_id from
6. where  type='D'
7. group by
8. on a.backup_set_id=b.backup_set_id and
9. --找出同组的备份组集合所有
10. union all
11. select A.database_name,A.backup_set_id,a.position, a.type,a.first_lsn,a.last_lsn,a.checkpoint_lsn,a.database_backup_lsn,isnull(datediff(d,backup_start_date,expiration_date),0) exp_day from
12. join
13. select A.database_name,A.backup_set_id,position, A.type,first_lsn,last_lsn,checkpoint_lsn,database_backup_lsn,isnull(datediff(d,backup_start_date,expiration_date),0) exp_day from
14. join (select database_name,MAX(backup_set_id) backup_set_id from
15. where type='D'
16. group by
17. on a.backup_set_id=b.backup_set_id and
18. ) b 
19. on a.database_backup_lsn=b.checkpoint_lsn AND
20. where a.type <>'D'
21.  
22. ) 
23. select  bf.*,cf.exp_day into
24. from
25. join
26. (select
27. bcs.backup_set_id, 
28. bcs.position, 
29. [BACK_TYPE]=bcs.type, 
30. [bacname]=bcs.name, 
31. bcs.database_name, 
32. [medianame]=bms.name, 
33. [BACdevicename]=bmf.logical_device_name, 
34. [dev_type]=bmf.device_type, 
35. [PHYS_DEVICE_NAME]=bmf.physical_device_name, 
36. bcs.expiration_date, 
37. --bcs.backup_set_uuid,
38. bcs.database_backup_lsn, 
39. bcs.first_lsn, 
40. bcs.last_lsn, 
41. bcs.checkpoint_lsn, 
42. --bcs.database_creation_date,
43. bcs.backup_start_date, 
44. bcs.backup_finish_date, 
45. [size/M]=bcs.compressed_backup_size/1024/1024 
46. from
47. join
48. join
49. on
50. on
51. on
52. where BACdevicename in
53. select name from
54. where name like '%My_bak%'
55. ) 
56. order by
57.  
58.  
59. SELECT DATABASE_NAME,[BACdevicename],back_type,count(1) times,MAX(backup_finish_date) last_time,SUM([size/M]) 'size/M' FROM
60. group by
61. order by
62.  
63. drop table

写出来分享给大家,希望大家提出好的建议和意见,也希望对大家有所帮助。