当前位置:Gxlcms > 数据库问题 > 关于SQL Server 数据库归档的一些思考和改进

关于SQL Server 数据库归档的一些思考和改进

时间:2021-07-01 10:21:17 帮助过:11人阅读

TABLE [dbo].[DBData_ArchiveConfig]( [ID] [int] IDENTITY(1,1) NOT NULL, [IP] [varchar](50) NULL, [DBName] [varchar](50) NULL, [DataTable] [varchar](50) NULL, [TargetIP] [varchar](50) NULL, [TargetDB] [varchar](50) NULL, [TargetTable] [varchar](50) NULL, [Prerequisite] [varchar](300) NULL, [DelMaxQTY] [int] NULL, [IsCheckOrderID] [int] NULL, [SP_Name] [int] NULL, [StartTime] [datetime] NULL, [EndTime] [datetime] NULL ) ON [PRIMARY] GO EXEC sys.sp_addextendedproperty @name=NMS_Description, @value=NServer IP(数据位于中央管理器中,所以归档数据库库所在的IP要维护,可维修虚拟的IP) , @level0type=NSCHEMA,@level0name=Ndbo, @level1type=NTABLE,@level1name=NDBData_ArchiveConfig, @level2type=NCOLUMN,@level2name=NIP GO EXEC sys.sp_addextendedproperty @name=NMS_Description, @value=N要归档的数据库 , @level0type=NSCHEMA,@level0name=Ndbo, @level1type=NTABLE,@level1name=NDBData_ArchiveConfig, @level2type=NCOLUMN,@level2name=NDBName GO EXEC sys.sp_addextendedproperty @name=NMS_Description, @value=N要归档的表 , @level0type=NSCHEMA,@level0name=Ndbo, @level1type=NTABLE,@level1name=NDBData_ArchiveConfig, @level2type=NCOLUMN,@level2name=NDataTable GO EXEC sys.sp_addextendedproperty @name=NMS_Description, @value=N备份指向的IP , @level0type=NSCHEMA,@level0name=Ndbo, @level1type=NTABLE,@level1name=NDBData_ArchiveConfig, @level2type=NCOLUMN,@level2name=NTargetIP GO EXEC sys.sp_addextendedproperty @name=NMS_Description, @value=N备份指向的数据库 , @level0type=NSCHEMA,@level0name=Ndbo, @level1type=NTABLE,@level1name=NDBData_ArchiveConfig, @level2type=NCOLUMN,@level2name=NTargetDB GO EXEC sys.sp_addextendedproperty @name=NMS_Description, @value=N备份指向的表 , @level0type=NSCHEMA,@level0name=Ndbo, @level1type=NTABLE,@level1name=NDBData_ArchiveConfig, @level2type=NCOLUMN,@level2name=NTargetTable GO EXEC sys.sp_addextendedproperty @name=NMS_Description, @value=N归档条件 , @level0type=NSCHEMA,@level0name=Ndbo, @level1type=NTABLE,@level1name=NDBData_ArchiveConfig, @level2type=NCOLUMN,@level2name=NPrerequisite GO EXEC sys.sp_addextendedproperty @name=NMS_Description, @value=N循环中一次归档删除的数据量 , @level0type=NSCHEMA,@level0name=Ndbo, @level1type=NTABLE,@level1name=NDBData_ArchiveConfig, @level2type=NCOLUMN,@level2name=NDelMaxQTY GO EXEC sys.sp_addextendedproperty @name=NMS_Description, @value=N此为 备用字段,考虑可能有些表,会和其他表关联 , @level0type=NSCHEMA,@level0name=Ndbo, @level1type=NTABLE,@level1name=NDBData_ArchiveConfig, @level2type=NCOLUMN,@level2name=NIsCheckOrderID GO EXEC sys.sp_addextendedproperty @name=NMS_Description, @value=N为提高并发度,一个DB对应的归档SP可能是多个,通过此列,进行分组。 , @level0type=NSCHEMA,@level0name=Ndbo, @level1type=NTABLE,@level1name=NDBData_ArchiveConfig, @level2type=NCOLUMN,@level2name=NSP_Name GO EXEC sys.sp_addextendedproperty @name=NMS_Description, @value=N此为拓展字段,原计划根据 开始时间、结束时间,每天可以多个时间段内执行 , @level0type=NSCHEMA,@level0name=Ndbo, @level1type=NTABLE,@level1name=NDBData_ArchiveConfig, @level2type=NCOLUMN,@level2name=NStartTime GO EXEC sys.sp_addextendedproperty @name=NMS_Description, @value=N此为拓展字段,原计划根据 开始时间、结束时间,每天可以多个时间段内执行 , @level0type=NSCHEMA,@level0name=Ndbo, @level1type=NTABLE,@level1name=NDBData_ArchiveConfig, @level2type=NCOLUMN,@level2name=NEndTime GO

2.2 归档运行的Log表

CREATE TABLE [dbo].[DBData_ArchiveLog](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [IP] [varchar](30) NULL,
    [DBName] [varchar](30) NULL,
    [DataTable] [varchar](80) NULL,
    [BakQTY] [varchar](30) NULL,
    [BakStartDate] [datetime] NULL,
    [BakEndDate] [datetime] NULL
) ON [PRIMARY]

GO

2.3 异常错误信息表

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

CREATE TABLE [dbo].[DBData_ArchiveErrLog](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [IP] [varchar](30) NULL,
    [DBName] [varchar](60) NULL,
    [DataTable] [varchar](80) NULL,
    [TargetIP] [varchar](30) NULL,
    [TargetDB] [varchar](60) NULL,
    [TargetTable] [varchar](80) NULL,
    [Errormsg] [nvarchar](max) NULL,
    [TransDateTime] [varchar](30) NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

GO

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

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

-- =============================================
-- Author:        <Author,,Name>
-- Create date: <Create Date,,>
-- Description:    <Description,,>
-- =============================================
CREATE PROCEDURE [dbo].[SP_XXXXX_DataArchive]
AS
    SET NOCOUNT ON;

    DECLARE @sql1 VARCHAR(MAX) 
    DECLARE @sql VARCHAR(MAX) 
    DECLARE @sql2 VARCHAR(MAX)
    DECLARE @IP VARCHAR(MAX) 
    DECLARE @DBName VARCHAR(MAX) 
    DECLARE @DataTable VARCHAR(MAX) 
    DECLARE @TargetIP VARCHAR(MAX) 
    DECLARE @TargetDB VARCHAR(MAX) 
    DECLARE @TargetTable VARCHAR(MAX) 
    DECLARE @Prerequisite VARCHAR(MAX) 
    DECLARE @DelMaxQTY INT
    DECLARE @StartTime DATETIME
    DECLARE @EndTime DATETIME
    DECLARE @qty INT 
    DECLARE @ISCHECKORDERID INT 
----Carson   2018-12-17 备份数据的时间往往比删除的时间长3倍,因此,如果考虑将备份的操作转移到辅助库,将会对线上的操作影响降至更低
    DECLARE @BakDateIP VARCHAR(30)  
    set @BakDateIP=[XXX.XXX.XXX.XXX].-------后面一定要有一个点
--------------------------------------------------归档操作---------------------------------
    DECLARE DBName CURSOR
    FOR
        SELECT  IP ,
                DBName ,
                DataTable ,
                TargetIP ,
                TargetDB ,
                TargetTable ,
                Prerequisite ,
                DelMaxQTY ,
                ISCHECKORDERID ,
                StartTime ,
                EndTime
        FROM    [中央管理器].[中央管理数据库].[dbo].[DBData_ArchiveConfig]
        WHERE   DataTable <> ‘‘
                AND TargetTable <> ‘‘
                AND DBNAME = XXXXXXXXX and SP_Name=?????
    OPEN DBName    
    FETCH NEXT FROM DBName INTO @IP, @DBName, @DataTable, @TargetIP, @TargetDB,
        @TargetTable, @Prerequisite, @DelMaxQTY, @ISCHECKORDERID,
        @StartTime, @EndTime   
    WHILE ( @@fetch_status = 0 )
    BEGIN  
        DECLARE @datetime DATETIME
        IF @ISCHECKORDERID <> 1  AND @DataTable <> ‘‘
        BEGIN
            SET @datetime = CONVERT(VARCHAR(10), GETDATE() - 30, 120)                
            SET @sql = Insert into [ + @TargetIP + ].
                + @TargetDB + . + dbo. + @TargetTable + 
                 select * FROM  + @BakDateIP + @DBName + . + dbo. + @DataTable +  
                 with(nolock) where  + @Prerequisite + ‘‘
                
            SET @sql1 = DECLARE @icount INTEGER  
                        SELECT @icount = COUNT(1)  
                        FROM  + @BakDateIP + @DBName + . + dbo. + @DataTable + 
                        where  + @Prerequisite +   
                        insert into [中央管理器].[中央管理数据库].dbo.DBData_ArchiveLog (IP, DBName, DataTable, BakQTY, BakStartDate, BakEndDate)
                        select ‘‘‘ + @IP + ‘‘‘,‘‘‘ + @DBName + ‘‘‘,‘‘‘ + @DataTable
                                    + ‘‘‘,@icount,getdate(),null

                        WHILE @icount > 0   
                        BEGIN  
                    
                            DELETE TOP ( + CAST(@DelMaxQTY AS VARCHAR(10)) + )  
                            FROM  + @DBName + . + dbo. + @DataTable +  
                            where  + @Prerequisite + 
      
                            SET @icount = @icount -(
                                    + CAST(@DelMaxQTY AS VARCHAR(10)) + )  
                            WAITFOR DELAY ‘‘00:00:01‘‘  
                        END                      
          BEGIN TRY
            EXEC (@sql)
            EXEC (@sql1) 
          END TRY
          BEGIN CATCH
             DECLARE @Errmsg AS nvarchar(MAX)
             SELECT @Errmsg=ERROR_MESSAGE()
               ------0001 BEGIN SAVE ERR LOG IN TABLE
               INSERT INTO [中央管理器].[中央管理数据库].[dbo].DBData_ArchiveErrLog  ([IP] ,[DBName],[DataTable],[TargetIP],[TargetDB],[TargetTable],[Errormsg] ,[TransDateTime])
               VALUES(@IP, @DBName, @DataTable, @TargetIP, @TargetDB, @TargetTable,@Errmsg,convert(VARCHAR(25),GETDATE(), 120))       
               ------0001 END
                -------------0002 BEGIN SEND EMAIL MESSAGE----------------              
                    DECLARE @Subject AS nvarchar(200)
                    DECLARE @Body AS nvarchar(MAX)
                    DECLARE @SPName AS nvarchar(MAX)
            
                    SET @Subject = 数据库归档异常 -重要!;ServerIP: + @IP +  DB: + @DBName
                                SET @SPName = ‘‘
                                SET @Body = <html><body>Dear All,<br> <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ServerIP: +@IP +  ; DataBase: + @DBName+ 上的Table归档异常,请及时检查!!!
                               <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;You can get detail information from the table. <br><br><table border=1 bgcolor=#aaff11> 
                                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>
                                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>
                                <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>
                                SET @Body = @Body + @SPName + </table>

                    SET @BODY=REPLACE(@BODY,‘‘‘‘,‘‘)

                    IF REPLACE(@BODY, ,‘‘)<>‘‘
                        BEGIN
                            DECLARE @AllEmailToAddress varchar(3000)=‘‘
                            DECLARE @AllEmailCcAddress varchar(3000)=‘‘
                            DECLARE @Allprofile_name varchar(100)=‘‘
                            SELECT @AllEmailToAddress=‘‘
                            SELECT @AllEmailCcAddress=‘‘
                            SELECT TOP 1 @Allprofile_name=NAME FROM msdb.dbo.sysmail_profile 
                            ORDER BY profile_id

                            EXEC msdb..sp_send_dbmail @profile_name = @Allprofile_name   -- profile 名称 
                             ,@recipients   =  @AllEmailToAddress        -- 收件人邮箱 
                             ,@copy_recipients=@AllEmailCcAddress
                             ,@subject      =  @Subject                  -- 邮件标题 
                                     

人气教程排行