经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 数据库/运维 » MS SQL Server » 查看文章
SQL Server 数据库基于备份文件的【一键还原】
来源:cnblogs  作者:东山絮柳仔  时间:2019/4/24 9:58:11  对本文有异议

1. 备份与还原的基础说明

我们知道在DBA的日常工作中,SQL Server 数据库的恢复请求偶有发生,可能是用作数据的追踪,可也可能能是数据库的灾难恢复。

数据库常用的备份命令如下:

  1. ----完整备份
  2. Declare @FullFileName Varchar(200)
  3. Declare @FileFlag varchar(20)
  4. Set @FileFlag=REPLACE(CONVERT(VARCHAR(10), GETDATE(), 120), '-','')+ REPLACE(CONVERT(VARCHAR(10), GETDATE(), 8), ':', '')
  5. Set @FullFileName='文档路径\数据库名字_FULL'+@FileFlag+'.bak'
  6. BackUp DataBase 数据库名字 To Disk=@FullFileName with init
  7. ----差异备份
  8. Declare @DiffFileName varchar(200)
  9. Declare @FileFlag varchar(200)
  10. Set @FileFlag=REPLACE(CONVERT(VARCHAR(10), GETDATE(), 120), '-','')+ REPLACE(CONVERT(VARCHAR(10), GETDATE(), 8), ':', '')
  11. Set @DiffFileName='文档路径\数据库名字_Diff_'+@FileFlag+'.bak'
  12. BackUp DataBase 数据库名字 To Disk=@DiffFileName with init,differential
  13. ----事务日志备份
  14. Declare @FileName Varchar(200)
  15. Declare @FileFlag varchar(20)
  16. Set @FileFlag=REPLACE(CONVERT(VARCHAR(10), GETDATE(), 120), '-','')+ REPLACE(CONVERT(VARCHAR(10), GETDATE(), 8), ':', '')
  17. Set @FileName='文档路径\数据库名字_Trn_'+@FileFlag+'.trn'
  18. BackUp Log 数据库名字 To Disk=@FileName with init

 

备份文件的命名格式为:数据库名字_备份类型(Full或Diff或Trn的一种)_时间格式.文件类型(bak或trn的一种) 

其中的时间格式为:年月日时分秒 ,例如:20190423140813。

例如,数据库TestRestoreOP的备份文件如下:

 

我们花费篇章来说明备份文件的格式化,主要是因为【一键】还原的基础是文件的标准化。

 

相应的还原命令如下:

  1. ----完整备份还原
  2. RESTORE DATABASE 数据库名字 FROM
  3. DISK = '完整备份的文件'---'TTTTTTT.BAK'
  4. WITH NORECOVERY, MOVE '数据库名字_Data' TO 'D:\指定路径\数据库名字_Data.mdf',
  5. MOVE '数据库名字_Log' TO 'D:\指定路径\数据库名字_Log.ldf'
  6.  
  7. ----差异备份还原
  8. RESTORE DATABASE 数据库名字 FROM
  9. DISK = '差异备份的文件'------'SSSSSSSSS.BAK'
  10. WITH NORECOVERY, MOVE '数据库名字_Data' TO 'D:\指定路径\数据库名字_Data.mdf',
  11. MOVE '数据库名字_Log' TO 'D:\指定路径\数据库名字_Log.ldf'
  12.  
  13. ----log备份还原
  14. RESTORE Log 数据库名字
  15. FROM DISK ='事务日志备份的文件' -----'XXXXXXXX.trn'
  16. WITH NORECOVERY

2.远程备份文件的【一键】还原

实际的生产中,我们常将备份文件Copy至远程服务器上,所以还原的时候,还要将这些文件Copy到指定服务上再进行还原。还有一种情况,就是Log还原可能需要逐一还原多个日志文件,有时候,甚至十几个文件需要还原。

针对这种这种情况,日常工作中,我们逐渐提炼成了以下SQL,替换参数后,基本实现 一键还原。

主要实现的功能有四点:

(1)将远程Server 上的指定备份路径下的文件Copy值本地指定路径;(如果文件以Copy值本地,这一步可以省略,对应的代码为1和2部分)

(2) 将这些文件属性读到表BackupFile;

(3)根据文件命名的时间属性,还原最近的一个完整备份 和一个差异备份;

(4)还原差异备份后产生的所有日志备份。

3.代码实现

  1. ---0 --定义要还原的数据库名字
  2. DECLARE @Cmd varchar (1024)
  3. DECLARE @dbName sysname
  4. Set @dbName='TestRestoreOP'
  5.  
  6. --- 1 --定义远程备份文件所在目录
  7. DECLARE @sourceFile NVARCHAR(500)
  8. SET @sourceFile = '\\169.XXX.XXX.XXX\d$\SQL_BackFile'
  9.  
  10. ----2 -- 将远程备份的目录,Copy至本地 D:\SQL_RestoreFile 目录下,MAXAGE:3 代表Copy最近3天的文件
  11. SET @Cmd=('master.dbo.xp_cmdshell '+'''ROBOCOPY.exe "'+@sourceFile+'" "D:\SQL_RestoreFile" *.* /E /XC /XN /X /MAXAGE:3 /MINAGE:0 ''')
  12. print @Cmd
  13. EXEC (@Cmd)
  14. Print '将远程需要还原的文件Copy至本地'
  15.  
  16. ----3 -- 获取还原文件List
  17. DECLARE @Path VARCHAR(260)
  18. SET @Path = 'D:\SQL_RestoreFile'
  19. IF RIGHT(@Path, 1) <> '\'
  20. SET @Path = @Path + '\'
  21. Print @Path
  22. ----判断表BackupFile是否已经存在,不存在则创建
  23. IF (SELECT COUNT(*) FROM SYS.sysobjects WHERE name='BackupFile'and xtype='U')=0
  24. BEGIN
  25. CREATE TABLE BackupFile
  26. (
  27. id INT , --编号
  28. directory VARCHAR(260) , --路径
  29. depth INT , --深度,相对与@path
  30. IsFile BIT ,
  31. filename VARCHAR(260),
  32. IsRestore int ,--是否还原
  33. )--0文件夹1文件名成
  34. END
  35.  
  36. Truncate table BackupFile
  37. -----判断表TMP_BackupFile是否已经存在,存在则删除再创建
  38. IF (SELECT COUNT(*) FROM SYS.sysobjects WHERE name='TMP_BackupFile'and xtype='U')<>0
  39. BEGIN
  40. DROP TABLE TMP_BackupFile
  41. END
  42. CREATE TABLE TMP_BackupFile
  43. (
  44. id INT IDENTITY , --编号
  45. directory VARCHAR(260) , --路径
  46. depth INT , --深度,相对与@path
  47. IsFile BIT ,
  48. filename VARCHAR(260),
  49. IsRestore int ,--是否还原
  50. )--0文件夹1文件名成
  51.  
  52.  
  53. ----将@Path 目录下结构读入到表TMP_BackupFile
  54. INSERT TMP_BackupFile
  55. ( directory ,
  56. depth ,
  57. IsFile
  58. )
  59. EXEC master.dbo.xp_dirtree @path = @Path, @depth = 0, @file = 1
  60.  
  61. update TMP_BackupFile set filename=directory,IsRestore=0
  62.  
  63. Print '将需要还原的文件信息读入到表TMP_BackupFile中'
  64.  
  65.  
  66. -----设置不需要还原的数据库文件,即删除
  67. DELETE FROM dbo.TMP_BackupFile WHERE directory NOT LIKE '%'+@dbName+'%'
  68.  
  69. ----设置删除不符合日期规则的文件
  70. DELETE FROM dbo.TMP_BackupFile WHERE left(right([filename],18),14)<'20190413015000'
  71.  
  72. -----更新目录
  73.  
  74. UPDATE TMP_BackupFile
  75. SET directory = @Path + directory
  76. WHERE depth = 1
  77.  
  78. ------
  79. if exists( select * from TMP_BackupFile WHERE depth > 1)
  80. begin
  81.  
  82. Print 'Error:备份文件所在的路径不对,或者@Path包含了不应该存在的文件夹目录!'
  83. end
  84. -------
  85.  
  86. INSERT INTO BackupFile (directory, depth, IsFile, [filename], IsRestore)
  87. SELECT B.directory, B.depth, B.IsFile, B.[filename], B.IsRestore FROM TMP_BackupFile B
  88. left join BackupFile e on B.[filename]=e.[filename] where e.[filename] is null
  89.  
  90.  
  91. ---4 --定义5/6/7 步骤需要的参数
  92.  
  93. DECLARE @filename NVARCHAR(500)
  94. DECLARE @backupPath NVARCHAR(500)
  95. -- 5 -- 找到需要还原的完整备份文件,进行完整还原
  96.  
  97. SELECT top 1 @filename =[filename] FROM BackupFile WHERE IsRestore=0 AND directory LIKE '%FULL%.bak' ORDER BY left(right([filename],18),14) desc
  98. Print @filename
  99. Print 'Msg:完整备份文件:' + @filename + '开始还原!'
  100.  
  101. SELECT @backupPath=directory
  102. FROM BackupFile WHERE filename=@filename AND IsRestore=0
  103. print @dbName
  104. SET @cmd = 'RESTORE DATABASE [' + @dbName + '] FROM DISK = '''
  105. + @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'
  106. exec (@cmd)
  107. PRINT @cmd
  108.  
  109. UPDATE BackupFile SET IsRestore=1 WHERE filename=@filename AND IsRestore=0
  110.  
  111. Print 'Msg:完整备份文件:' + @filename + '还原完成!'
  112.  
  113. -- 6 --- 找到需要还原的差异备份文件,进行增量还原
  114.  
  115. SELECT top 1 @filename=[filename] FROM BackupFile WHERE IsRestore=0 AND directory LIKE '%Diff%.bak' ORDER BY left(right([filename],18),14) desc
  116. print @filename
  117.  
  118. Print 'Msg:获取得知需要还原的差异备份文件:' + @filename + ',此时将不需要还原的差异文件/日志文件设置为不需要还原'
  119. update BackupFile set IsRestore=10
  120. WHERE IsRestore=0 AND
  121. (directory LIKE '%Diff%.bak' or directory LIKE '%TRN%.TRN' ) and left(right([filename],18),14)<left(right( @filename,18),14)
  122. Print 'Msg:差异备份文件:' + @filename + '开始还原!'
  123.  
  124. SELECT @backupPath=directory FROM BackupFile WHERE filename=@filename AND IsRestore=0
  125. SET @cmd = 'RESTORE DATABASE [' + @dbName + '] FROM DISK = '''
  126. + @backupPath + ''' WITH NORECOVERY'
  127. exec(@cmd)
  128. PRINT @cmd
  129.  
  130. UPDATE BackupFile SET IsRestore=1 WHERE filename=@filename AND IsRestore=0
  131.  
  132. Print 'Msg:差异备份文件:' + @filename + '还原完成!'
  133.  
  134. -- 7 --日志备份文件还原
  135. DECLARE filenames CURSOR FOR
  136. SELECT [filename] FROM BackupFile WHERE IsRestore=0 AND directory LIKE '%TRN%.TRN' ORDER BY left(right([filename],18),14) asc
  137. OPEN filenames
  138. -- Loop through all the files for the database
  139. FETCH NEXT FROM filenames INTO @filename
  140. WHILE @@FETCH_STATUS = 0
  141. BEGIN
  142.  
  143. Print 'Msg:日志备份文件:' + @filename + '开始还原!'
  144. SELECT @backupPath=directory FROM BackupFile WHERE filename=@filename AND IsRestore=0
  145. SET @cmd = 'RESTORE LOG [' + @dbName + '] FROM DISK = '''
  146. +@backupPath+ ''' WITH NORECOVERY'
  147. exec(@cmd)
  148. UPDATE BackupFile SET IsRestore=1 WHERE filename=@filename AND IsRestore=0
  149.  
  150. Print 'Msg:日志备份文件:' + @filename + '还原完成!'
  151.  
  152. PRINT @cmd
  153. FETCH NEXT FROM filenames INTO @filename
  154. END
  155. CLOSE filenames
  156. DEALLOCATE filenames
  157. -- 8 -- 将数据库的状态由真正还原Restore正常状态!
  158.  
  159. Print '将数据库的状态由真正还原Restore正常状态!'
  160. SET @cmd = 'RESTORE DATABASE [' + @dbName + '] WITH RECOVERY'
  161. PRINT @cmd
  162.  
  163. Print '数据库所有的还原操作都已完成!'---0 --定义要还原的数据库名字
  164. DECLARE @Cmd varchar (1024)
  165. DECLARE @dbName sysname
  166. Set @dbName='TestRestoreOP'
  167.  
  168. --- 1 --定义远程备份文件所在目录
  169. DECLARE @sourceFile NVARCHAR(500)
  170. SET @sourceFile = '\\169.XXX.XXX.XXX\d$\SQL_BackFile'
  171.  
  172. ----2 -- 将远程备份的目录,Copy至本地 D:\SQL_RestoreFile 目录下,MAXAGE:3 代表Copy最近3天的文件
  173. SET @Cmd=('master.dbo.xp_cmdshell '+'''ROBOCOPY.exe "'+@sourceFile+'" "D:\SQL_RestoreFile" *.* /E /XC /XN /X /MAXAGE:3 /MINAGE:0 ''')
  174. print @Cmd
  175. EXEC (@Cmd)
  176. Print '将远程需要还原的文件Copy至本地'
  177.  
  178. ----3 -- 获取还原文件List
  179. DECLARE @Path VARCHAR(260)
  180. SET @Path = 'D:\SQL_RestoreFile'
  181. IF RIGHT(@Path, 1) <> '\'
  182. SET @Path = @Path + '\'
  183. Print @Path
  184. ----判断表BackupFile是否已经存在,不存在则创建
  185. IF (SELECT COUNT(*) FROM SYS.sysobjects WHERE name='BackupFile'and xtype='U')=0
  186. BEGIN
  187. CREATE TABLE BackupFile
  188. (
  189. id INT , --编号
  190. directory VARCHAR(260) , --路径
  191. depth INT , --深度,相对与@path
  192. IsFile BIT ,
  193. filename VARCHAR(260),
  194. IsRestore int ,--是否还原
  195. )--0文件夹1文件名成
  196. END
  197.  
  198. Truncate table BackupFile
  199. -----判断表TMP_BackupFile是否已经存在,存在则删除再创建
  200. IF (SELECT COUNT(*) FROM SYS.sysobjects WHERE name='TMP_BackupFile'and xtype='U')<>0
  201. BEGIN
  202. DROP TABLE TMP_BackupFile
  203. END
  204. CREATE TABLE TMP_BackupFile
  205. (
  206. id INT IDENTITY , --编号
  207. directory VARCHAR(260) , --路径
  208. depth INT , --深度,相对与@path
  209. IsFile BIT ,
  210. filename VARCHAR(260),
  211. IsRestore int ,--是否还原
  212. )--0文件夹1文件名成
  213.  
  214.  
  215. ----将@Path 目录下结构读入到表TMP_BackupFile
  216. INSERT TMP_BackupFile
  217. ( directory ,
  218. depth ,
  219. IsFile
  220. )
  221. EXEC master.dbo.xp_dirtree @path = @Path, @depth = 0, @file = 1
  222.  
  223. update TMP_BackupFile set filename=directory,IsRestore=0
  224.  
  225. Print '将需要还原的文件信息读入到表TMP_BackupFile中'
  226.  
  227.  
  228. -----设置不需要还原的数据库文件,即删除
  229. DELETE FROM dbo.TMP_BackupFile WHERE directory NOT LIKE '%'+@dbName+'%'
  230.  
  231. ----设置删除不符合日期规则的文件
  232. DELETE FROM dbo.TMP_BackupFile WHERE left(right([filename],18),14)<'20190413015000'
  233.  
  234. -----更新目录
  235.  
  236. UPDATE TMP_BackupFile
  237. SET directory = @Path + directory
  238. WHERE depth = 1
  239.  
  240. ------
  241. if exists( select * from TMP_BackupFile WHERE depth > 1)
  242. begin
  243.  
  244. Print 'Error:备份文件所在的路径不对,或者@Path包含了不应该存在的文件夹目录!'
  245. end
  246. -------
  247.  
  248. INSERT INTO BackupFile (directory, depth, IsFile, [filename], IsRestore)
  249. SELECT B.directory, B.depth, B.IsFile, B.[filename], B.IsRestore FROM TMP_BackupFile B
  250. left join BackupFile e on B.[filename]=e.[filename] where e.[filename] is null
  251.  
  252.  
  253. ---4 --定义5/6/7 步骤需要的参数
  254.  
  255. DECLARE @filename NVARCHAR(500)
  256. DECLARE @backupPath NVARCHAR(500)
  257. -- 5 -- 找到需要还原的完整备份文件,进行完整还原
  258.  
  259. SELECT top 1 @filename =[filename] FROM BackupFile WHERE IsRestore=0 AND directory LIKE '%FULL%.bak' ORDER BY left(right([filename],18),14) desc
  260. Print @filename
  261. Print 'Msg:完整备份文件:' + @filename + '开始还原!'
  262.  
  263. SELECT @backupPath=directory
  264. FROM BackupFile WHERE filename=@filename AND IsRestore=0
  265. print @dbName
  266. SET @cmd = 'RESTORE DATABASE [' + @dbName + '] FROM DISK = '''
  267. + @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'
  268. exec (@cmd)
  269. PRINT @cmd
  270.  
  271. UPDATE BackupFile SET IsRestore=1 WHERE filename=@filename AND IsRestore=0
  272.  
  273. Print 'Msg:完整备份文件:' + @filename + '还原完成!'
  274.  
  275. -- 6 --- 找到需要还原的差异备份文件,进行增量还原
  276.  
  277. SELECT top 1 @filename=[filename] FROM BackupFile WHERE IsRestore=0 AND directory LIKE '%Diff%.bak' ORDER BY left(right([filename],18),14) desc
  278. print @filename
  279.  
  280. Print 'Msg:获取得知需要还原的差异备份文件:' + @filename + ',此时将不需要还原的差异文件/日志文件设置为不需要还原'
  281. update BackupFile set IsRestore=10
  282. WHERE IsRestore=0 AND
  283. (directory LIKE '%Diff%.bak' or directory LIKE '%TRN%.TRN' ) and left(right([filename],18),14)<left(right( @filename,18),14)
  284. Print 'Msg:差异备份文件:' + @filename + '开始还原!'
  285.  
  286. SELECT @backupPath=directory FROM BackupFile WHERE filename=@filename AND IsRestore=0
  287. SET @cmd = 'RESTORE DATABASE [' + @dbName + '] FROM DISK = '''
  288. + @backupPath + ''' WITH NORECOVERY'
  289. exec(@cmd)
  290. PRINT @cmd
  291.  
  292. UPDATE BackupFile SET IsRestore=1 WHERE filename=@filename AND IsRestore=0
  293.  
  294. Print 'Msg:差异备份文件:' + @filename + '还原完成!'
  295.  
  296. -- 7 --日志备份文件还原
  297. DECLARE filenames CURSOR FOR
  298. SELECT [filename] FROM BackupFile WHERE IsRestore=0 AND directory LIKE '%TRN%.TRN' ORDER BY left(right([filename],18),14) asc
  299. OPEN filenames
  300. -- Loop through all the files for the database
  301. FETCH NEXT FROM filenames INTO @filename
  302. WHILE @@FETCH_STATUS = 0
  303. BEGIN
  304.  
  305. Print 'Msg:日志备份文件:' + @filename + '开始还原!'
  306. SELECT @backupPath=directory FROM BackupFile WHERE filename=@filename AND IsRestore=0
  307. SET @cmd = 'RESTORE LOG [' + @dbName + '] FROM DISK = '''
  308. +@backupPath+ ''' WITH NORECOVERY'
  309. exec(@cmd)
  310. UPDATE BackupFile SET IsRestore=1 WHERE filename=@filename AND IsRestore=0
  311.  
  312. Print 'Msg:日志备份文件:' + @filename + '还原完成!'
  313.  
  314. PRINT @cmd
  315. FETCH NEXT FROM filenames INTO @filename
  316. END
  317. CLOSE filenames
  318. DEALLOCATE filenames
  319. -- 8 -- 将数据库的状态由真正还原Restore正常状态!
  320.  
  321. Print '将数据库的状态由真正还原Restore正常状态!'
  322. SET @cmd = 'RESTORE DATABASE [' + @dbName + '] WITH RECOVERY'
    exec(@cmd)
  323. PRINT @cmd
  324.  
  325. Print '数据库所有的还原操作都已完成!'

 

如果在您工作中也有类似需求,需要执行上述代码,则需要替换的参数如下

需要替换的参数数据
参数 代表含义
@dbName 需还原的数据库名字,本例为;
  1. TestRestoreOP
  1. @sourceFile
备份文件在远程Server路径;本例为
  1. \\169.XXX.XXX.XXX\d$\SQL_BackFile
没有设置参数 备份文件copy至本地的路径;本例为
  1. D:\SQL_RestoreFile
 没有设置参数
  1. 设置删除不符合日期规则的文件,指的是把旧的文件也Copy到本地了,这还原表中因删除;本例为
  1. 20190413015000
 没有设置参数
  1. 设置还原数据库的数据文件所在文档路径:本例为 D:\sql_data\。建议不要修改,执行前请先创建。
 没有设置参数
  1. 设置还原数据库的日志文件所在文档路径;本例为 D:\sql_log\
  1. 。建议不要修改,执行前请先创建。

 

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共同完成。

未经作者同意不得转载,谢谢配合!!!

原文链接:http://www.cnblogs.com/xuliuzai/p/10752629.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号