经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 数据库/运维 » MS SQL Server » 查看文章
关于SQL Server 数据库归档的一些思考和改进
来源:cnblogs  作者:东山絮柳仔  时间:2018/12/25 9:24:38  对本文有异议

一.需求背景

SQL Server开源的归档工具不多,DBA一般都是通过计划任务来触发执行,执行的脚本多是SP或者是SSIS包。SSIS包的性能稍好一些,但是维护更新成本高些。所以更常见的是通过SP脚本来实现归档操作。

当数据库规模较小时,可以方便的直接在数据库上进行脚本的编写部署。但是随着数据库越来越多,管理维护成本就会越来越大,越来越不方便。现在我们实行的方式是通过中央管理器来管理众多的数据库备份(这是在拥有专门的备份程序前的一个过渡方案)。我们将归档基础配置信息、归档运行历史记录、异常报错等数据统一维护在中央数据库上。如此,可以方便统一的查看、管理和维护。

 二.主要架构

 

三.主要关联表

2.1 归档基础配置表

表字段含义,请耐心查看字段说明。

  1. CREATE TABLE [dbo].[DBData_ArchiveConfig](
  2. [ID] [int] IDENTITY(1,1) NOT NULL,
  3. [IP] [varchar](50) NULL,
  4. [DBName] [varchar](50) NULL,
  5. [DataTable] [varchar](50) NULL,
  6. [TargetIP] [varchar](50) NULL,
  7. [TargetDB] [varchar](50) NULL,
  8. [TargetTable] [varchar](50) NULL,
  9. [Prerequisite] [varchar](300) NULL,
  10. [DelMaxQTY] [int] NULL,
  11. [IsCheckOrderID] [int] NULL,
  12. [SP_Name] [int] NULL,
  13. [StartTime] [datetime] NULL,
  14. [EndTime] [datetime] NULL
  15. ) ON [PRIMARY]
  16.  
  17. GO
  18.  
  19. EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'Server IP(数据位于中央管理器中,所以归档数据库库所在的IP要维护,可维修虚拟的IP)' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'DBData_ArchiveConfig', @level2type=N'COLUMN',@level2name=N'IP'
  20. GO
  21.  
  22. EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'要归档的数据库' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'DBData_ArchiveConfig', @level2type=N'COLUMN',@level2name=N'DBName'
  23. GO
  24.  
  25. EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'要归档的表' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'DBData_ArchiveConfig', @level2type=N'COLUMN',@level2name=N'DataTable'
  26. GO
  27.  
  28. EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'备份指向的IP' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'DBData_ArchiveConfig', @level2type=N'COLUMN',@level2name=N'TargetIP'
  29. GO
  30.  
  31. EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'备份指向的数据库' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'DBData_ArchiveConfig', @level2type=N'COLUMN',@level2name=N'TargetDB'
  32. GO
  33.  
  34. EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'备份指向的表' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'DBData_ArchiveConfig', @level2type=N'COLUMN',@level2name=N'TargetTable'
  35. GO
  36.  
  37. EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'归档条件' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'DBData_ArchiveConfig', @level2type=N'COLUMN',@level2name=N'Prerequisite'
  38. GO
  39.  
  40. EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'循环中一次归档删除的数据量' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'DBData_ArchiveConfig', @level2type=N'COLUMN',@level2name=N'DelMaxQTY'
  41. GO
  42.  
  43. EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'此为 备用字段,考虑可能有些表,会和其他表关联' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'DBData_ArchiveConfig', @level2type=N'COLUMN',@level2name=N'IsCheckOrderID'
  44. GO
  45.  
  46. EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'为提高并发度,一个DB对应的归档SP可能是多个,通过此列,进行分组。' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'DBData_ArchiveConfig', @level2type=N'COLUMN',@level2name=N'SP_Name'
  47. GO
  48.  
  49. EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'此为拓展字段,原计划根据 开始时间、结束时间,每天可以多个时间段内执行' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'DBData_ArchiveConfig', @level2type=N'COLUMN',@level2name=N'StartTime'
  50. GO
  51.  
  52. EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'此为拓展字段,原计划根据 开始时间、结束时间,每天可以多个时间段内执行' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'DBData_ArchiveConfig', @level2type=N'COLUMN',@level2name=N'EndTime'
  53. GO

2.2 归档运行的Log表

  1. CREATE TABLE [dbo].[DBData_ArchiveLog](
  2. [ID] [int] IDENTITY(1,1) NOT NULL,
  3. [IP] [varchar](30) NULL,
  4. [DBName] [varchar](30) NULL,
  5. [DataTable] [varchar](80) NULL,
  6. [BakQTY] [varchar](30) NULL,
  7. [BakStartDate] [datetime] NULL,
  8. [BakEndDate] [datetime] NULL
  9. ) ON [PRIMARY]
  10.  
  11. GO

2.3 异常错误信息表

执行的过程中会外包一层 try...catch,将操作过程中的错误信息保存在表 DBData_ArchiveErrLog。表结构如下:

  1. CREATE TABLE [dbo].[DBData_ArchiveErrLog](
  2. [ID] [int] IDENTITY(1,1) NOT NULL,
  3. [IP] [varchar](30) NULL,
  4. [DBName] [varchar](60) NULL,
  5. [DataTable] [varchar](80) NULL,
  6. [TargetIP] [varchar](30) NULL,
  7. [TargetDB] [varchar](60) NULL,
  8. [TargetTable] [varchar](80) NULL,
  9. [Errormsg] [nvarchar](max) NULL,
  10. [TransDateTime] [varchar](30) NULL
  11. ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
  12.  
  13. GO

四. 存储过程相应的主要代码

  1. SET ANSI_NULLS ON
  2. GO
  3.  
  4. SET QUOTED_IDENTIFIER ON
  5. GO
  6.  
  7. -- =============================================
  8. -- Author: <Author,,Name>
  9. -- Create date: <Create Date,,>
  10. -- Description: <Description,,>
  11. -- =============================================
  12. CREATE PROCEDURE [dbo].[SP_XXXXX_DataArchive]
  13. AS
  14. SET NOCOUNT ON;
  15. DECLARE @sql1 VARCHAR(MAX)
  16. DECLARE @sql VARCHAR(MAX)
  17. DECLARE @sql2 VARCHAR(MAX)
  18. DECLARE @IP VARCHAR(MAX)
  19. DECLARE @DBName VARCHAR(MAX)
  20. DECLARE @DataTable VARCHAR(MAX)
  21. DECLARE @TargetIP VARCHAR(MAX)
  22. DECLARE @TargetDB VARCHAR(MAX)
  23. DECLARE @TargetTable VARCHAR(MAX)
  24. DECLARE @Prerequisite VARCHAR(MAX)
  25. DECLARE @DelMaxQTY INT
  26. DECLARE @StartTime DATETIME
  27. DECLARE @EndTime DATETIME
  28. DECLARE @qty INT
  29. DECLARE @ISCHECKORDERID INT
  30. ----Carson 2018-12-17 备份数据的时间往往比删除的时间长3倍,因此,如果考虑将备份的操作转移到辅助库,将会对线上的操作影响降至更低
  31. DECLARE @BakDateIP VARCHAR(30)
  32. set @BakDateIP='[XXX.XXX.XXX.XXX].'-------后面一定要有一个点
  33. --------------------------------------------------归档操作---------------------------------
  34. DECLARE DBName CURSOR
  35. FOR
  36. SELECT IP ,
  37. DBName ,
  38. DataTable ,
  39. TargetIP ,
  40. TargetDB ,
  41. TargetTable ,
  42. Prerequisite ,
  43. DelMaxQTY ,
  44. ISCHECKORDERID ,
  45. StartTime ,
  46. EndTime
  47. FROM [中央管理器].[中央管理数据库].[dbo].[DBData_ArchiveConfig]
  48. WHERE DataTable <> ''
  49. AND TargetTable <> ''
  50. AND DBNAME = 'XXXXXXXXX' and SP_Name='?????'
  51. OPEN DBName
  52. FETCH NEXT FROM DBName INTO @IP, @DBName, @DataTable, @TargetIP, @TargetDB,
  53. @TargetTable, @Prerequisite, @DelMaxQTY, @ISCHECKORDERID,
  54. @StartTime, @EndTime
  55. WHILE ( @@fetch_status = 0 )
  56. BEGIN
  57. DECLARE @datetime DATETIME
  58. IF @ISCHECKORDERID <> '1' AND @DataTable <> ''
  59. BEGIN
  60. SET @datetime = CONVERT(VARCHAR(10), GETDATE() - 30, 120)
  61. SET @sql = 'Insert into [' + @TargetIP + '].'
  62. + @TargetDB + '.' + 'dbo.' + @TargetTable + '
  63. select * FROM ' + @BakDateIP + @DBName + '.' + 'dbo.' + @DataTable + '
  64. with(nolock) where ' + @Prerequisite + ''
  65. SET @sql1 = 'DECLARE @icount INTEGER
  66. SELECT @icount = COUNT(1)
  67. FROM ' + @BakDateIP + @DBName + '.' + 'dbo.' + @DataTable + '
  68. where ' + @Prerequisite + '
  69. insert into [中央管理器].[中央管理数据库].dbo.DBData_ArchiveLog (IP, DBName, DataTable, BakQTY, BakStartDate, BakEndDate)
  70. select ''' + @IP + ''',''' + @DBName + ''',''' + @DataTable
  71. + ''',@icount,getdate(),null
  72. WHILE @icount > 0
  73. BEGIN
  74. DELETE TOP (' + CAST(@DelMaxQTY AS VARCHAR(10)) + ')
  75. FROM ' + @DBName + '.' + 'dbo.' + @DataTable + '
  76. where ' + @Prerequisite + '
  77. SET @icount = @icount -('
  78. + CAST(@DelMaxQTY AS VARCHAR(10)) + ')
  79. WAITFOR DELAY ''00:00:01''
  80. END '
  81. BEGIN TRY
  82. EXEC (@sql)
  83. EXEC (@sql1)
  84. END TRY
  85. BEGIN CATCH
  86. DECLARE @Errmsg AS nvarchar(MAX)
  87. SELECT @Errmsg=ERROR_MESSAGE()
  88. ------0001 BEGIN SAVE ERR LOG IN TABLE
  89. INSERT INTO [中央管理器].[中央管理数据库].[dbo].DBData_ArchiveErrLog ([IP] ,[DBName],[DataTable],[TargetIP],[TargetDB],[TargetTable],[Errormsg] ,[TransDateTime])
  90. VALUES(@IP, @DBName, @DataTable, @TargetIP, @TargetDB, @TargetTable,@Errmsg,convert(VARCHAR(25),GETDATE(), 120))
  91. ------0001 END
  92. -------------0002 BEGIN SEND EMAIL MESSAGE----------------
  93. DECLARE @Subject AS nvarchar(200)
  94. DECLARE @Body AS nvarchar(MAX)
  95. DECLARE @SPName AS nvarchar(MAX)
  96. SET @Subject = '数据库归档异常 -重要!;ServerIP:' + @IP + ' DB:' + @DBName
  97. SET @SPName = ''
  98. SET @Body = '<html><body>Dear All,<br> <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ServerIP:' +@IP + ' ; DataBase:' + @DBName+ '上的Table归档异常,请及时检查!!!
  99. <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;You can get detail information from the table. <br><br><table border=1 bgcolor=#aaff11>'
  100. SET @Body = @Body+ '<tr bgcolor=#ff3311><td>ServerIP</td><td>DBName</td><td>TableName</td><td>TargetIP</td><td>TargetDB</td><td>Errmsg</td><td>TransDateTime</td></tr>'
  101. SELECT @SPName = @SPName + '<tr bgcolor=#ffaa11><td>'+ CAST(@IP AS NVARCHAR(50))+ '</td><td>' + CAST(@DBName AS NVARCHAR(50)) + '</td><td>'+CAST(@DataTable AS NVARCHAR(50))+ '</td>
  102. <td>'+ CAST(@TargetIP AS NVARCHAR(20))+ '</td><td>'+ CAST(@TargetDB AS NVARCHAR(50))+ '</td><td>'+ SUBSTRING(@Errmsg,1, 100)+ '</td><td>'+ CONVERT(varchar(100), GETDATE(), 21)+ '</td></tr>'
  103. SET @Body = @Body + @SPName + '</table>'
  104.  
  105. SET @BODY=REPLACE(@BODY,'''','')
  106. IF REPLACE(@BODY,' ','')<>''
  107. BEGIN
  108. DECLARE @AllEmailToAddress varchar(3000)=''
  109. DECLARE @AllEmailCcAddress varchar(3000)=''
  110. DECLARE @Allprofile_name varchar(100)=''
  111. SELECT @AllEmailToAddress=''
  112. SELECT @AllEmailCcAddress=''
  113. SELECT TOP 1 @Allprofile_name=NAME FROM msdb.dbo.sysmail_profile
  114. ORDER BY profile_id
  115. EXEC msdb..sp_send_dbmail @profile_name = @Allprofile_name -- profile 名称
  116. ,@recipients = @AllEmailToAddress -- 收件人邮箱
  117. ,@copy_recipients=@AllEmailCcAddress
  118. ,@subject = @Subject -- 邮件标题
  119. ,@body = @BODY -- 邮件内容
  120. ,@body_format = 'HTML' -- 邮件格式
  121. ,@file_attachments=''
  122. ,@Importance = 'High'
  123. END
  124. ------------- 0002 end ------------
  125. END CATCH
  126. END
  127.  
  128. FETCH NEXT FROM DBName INTO @IP, @DBName, @DataTable, @TargetIP,
  129. @TargetDB, @TargetTable, @Prerequisite, @DelMaxQTY,
  130. @ISCHECKORDERID, @StartTime, @EndTime
  131. END
  132. CLOSE DBName
  133. DEALLOCATE DBName
  134. DECLARE DELETETABLE CURSOR
  135. FOR
  136. SELECT IP ,
  137. DBName ,
  138. DataTable ,
  139. TargetTable ,
  140. Prerequisite ,
  141. DelMaxQTY
  142. FROM [中央管理器].[中央管理数据库].[dbo].[DBData_ArchiveConfig]
  143. WHERE DataTable <> ''
  144. AND TargetTable = ''
  145. AND DBNAME = 'XXXXXXXXX' and SP_Name='????'
  146. OPEN DELETETABLE
  147. FETCH NEXT FROM DELETETABLE INTO @IP, @DBName, @DataTable,
  148. @TargetTable, @Prerequisite, @DelMaxQTY
  149. WHILE ( @@fetch_status = 0 )
  150. BEGIN
  151. SET @sql1 = 'DECLARE @icount INTEGER
  152. SELECT @icount = COUNT(1)
  153. FROM ' + @DBName + '.' + 'dbo.' + @DataTable + '
  154. where ' + @Prerequisite + '
  155. WHILE @icount > 0
  156. BEGIN
  157. DELETE TOP (' + CAST(@DelMaxQTY AS VARCHAR(10)) + ')
  158. FROM ' + @DBName + '.' + 'dbo.' + @DataTable + '
  159. where ' + @Prerequisite + '
  160. SET @icount = @icount -('
  161. + CAST(@DelMaxQTY AS VARCHAR(10)) + ')
  162. WAITFOR DELAY ''00:00:01''
  163. END '
  164. PRINT @sql1
  165. EXEC (@sql1)
  166. FETCH NEXT FROM DELETETABLE INTO @IP, @DBName, @DataTable,@TargetTable, @Prerequisite, @DelMaxQTY
  167. END
  168. CLOSE DELETETABLE
  169. DEALLOCATE DELETETABLE
  170. GO

五.补充数据

1.数据库归档,一般都是先将当前库的历史数据归档到历史库,再将当前库的历史数据删除。这两个阶段,一般是前者耗时较多(一般都在2:1以上),虽然可以在select 过程加上nolock,但是或者I/O或者网络等原因,其实这个阶段对应用程序的影响还是比较大的。所以,建议将这两个阶段物理分开,即如果有配置AlwaysOn,请将第一个阶段在辅助数据库中执行。上面的SP示例,就是通过参数 @BakDateIP 来实现了这一作用。

2.存储过程中包含了try...catch,所以运行此sp就会很少报错,某一个表的异常不会相互影响。例如,我们常见的当前库、历史库由于表结构变更而导致的不一致,此情况出现后,try..catch可以捕捉到异常,将异常记录在档,并将此信息以邮件的形式发送给指定人,但整个SP不会执行失败。并且还会跳过这一个异常,继续执行下一个备份归档表的归档。

 

本文版权归作者所有,未经作者同意不得转载,谢谢配合!!!

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

本站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号