一。需求背景 SQLServer开源的归档工具不多,DBA一般都是通过计划任务来触发执行,执行的脚本多是SP或者是SSIS包。SSIS包的性能稍好一些,但是维护更新成本高些。所以更常见的是通过SP脚本来实现归档操作。 当数据库规模较小时,可以方便的直接在数据库上进行脚本的编写部署。但是随着数据库越来越多,管理维护成本就会越来越大,越来越不方便。现在我们实行的方式是通过中央管理器来管理众多的数据库备份(这是在拥有专门的备份程序前的一个过渡方案)。我们将归档基础配置信息、归档运行历史记录、异常报错等数据统一维护在中央数据库上。如此,可以方便统一的查看、管理和维护。 二。主要架构 三。主要关联表 2。1归档基础配置表 表字段含义,请耐心查看字段说明。 CREATETABLE〔dbo〕。〔DBDataArchiveConfig〕( 〔ID〕〔int〕IDENTITY(1,1)NOTNULL, 〔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, 〔SPName〕〔int〕NULL, 〔StartTime〕〔datetime〕NULL, 〔EndTime〕〔datetime〕NULL )ON〔PRIMARY〕 GO EXECsys。spaddextendedpropertynameNMSDescription,valueNServerIP(数据位于中央管理器中,所以归档数据库库所在的IP要维护,可维修虚拟的IP),level0typeNSCHEMA,level0nameNdbo,level1typeNTABLE,level1nameNDBDataArchiveConfig,level2typeNCOLUMN,level2nameNIP GO EXECsys。spaddextendedpropertynameNMSDescription,valueN要归档的数据库,level0typeNSCHEMA,level0nameNdbo,level1typeNTABLE,level1nameNDBDataArchiveConfig,level2typeNCOLUMN,level2nameNDBName GO EXECsys。spaddextendedpropertynameNMSDescription,valueN要归档的表,level0typeNSCHEMA,level0nameNdbo,level1typeNTABLE,level1nameNDBDataArchiveConfig,level2typeNCOLUMN,level2nameNDataTable GO EXECsys。spaddextendedpropertynameNMSDescription,valueN备份指向的IP,level0typeNSCHEMA,level0nameNdbo,level1typeNTABLE,level1nameNDBDataArchiveConfig,level2typeNCOLUMN,level2nameNTargetIP GO EXECsys。spaddextendedpropertynameNMSDescription,valueN备份指向的数据库,level0typeNSCHEMA,level0nameNdbo,level1typeNTABLE,level1nameNDBDataArchiveConfig,level2typeNCOLUMN,level2nameNTargetDB GO EXECsys。spaddextendedpropertynameNMSDescription,valueN备份指向的表,level0typeNSCHEMA,level0nameNdbo,level1typeNTABLE,level1nameNDBDataArchiveConfig,level2typeNCOLUMN,level2nameNTargetTable GO EXECsys。spaddextendedpropertynameNMSDescription,valueN归档条件,level0typeNSCHEMA,level0nameNdbo,level1typeNTABLE,level1nameNDBDataArchiveConfig,level2typeNCOLUMN,level2nameNPrerequisite GO EXECsys。spaddextendedpropertynameNMSDescription,valueN循环中一次归档删除的数据量,level0typeNSCHEMA,level0nameNdbo,level1typeNTABLE,level1nameNDBDataArchiveConfig,level2typeNCOLUMN,level2nameNDelMaxQTY GO EXECsys。spaddextendedpropertynameNMSDescription,valueN此为备用字段,考虑可能有些表,会和其他表关联,level0typeNSCHEMA,level0nameNdbo,level1typeNTABLE,level1nameNDBDataArchiveConfig,level2typeNCOLUMN,level2nameNIsCheckOrderID GO EXECsys。spaddextendedpropertynameNMSDescription,valueN为提高并发度,一个DB对应的归档SP可能是多个,通过此列,进行分组。,level0typeNSCHEMA,level0nameNdbo,level1typeNTABLE,level1nameNDBDataArchiveConfig,level2typeNCOLUMN,level2nameNSPName GO EXECsys。spaddextendedpropertynameNMSDescription,valueN此为拓展字段,原计划根据开始时间、结束时间,每天可以多个时间段内执行,level0typeNSCHEMA,level0nameNdbo,level1typeNTABLE,level1nameNDBDataArchiveConfig,level2typeNCOLUMN,level2nameNStartTime GO EXECsys。spaddextendedpropertynameNMSDescription,valueN此为拓展字段,原计划根据开始时间、结束时间,每天可以多个时间段内执行,level0typeNSCHEMA,level0nameNdbo,level1typeNTABLE,level1nameNDBDataArchiveConfig,level2typeNCOLUMN,level2nameNEndTime GO 2。2归档运行的Log表 CREATETABLE〔dbo〕。〔DBDataArchiveLog〕( 〔ID〕〔int〕IDENTITY(1,1)NOTNULL, 〔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,将操作过程中的错误信息保存在表DBDataArchiveErrLog。表结构如下: CREATETABLE〔dbo〕。〔DBDataArchiveErrLog〕( 〔ID〕〔int〕IDENTITY(1,1)NOTNULL, 〔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〕TEXTIMAGEON〔PRIMARY〕 GO 四。存储过程相应的主要代码 SETANSINULLSON GO SETQUOTEDIDENTIFIERON GO Author: Createdate: Description: CREATEPROCEDURE〔dbo〕。〔SPXXXXXDataArchive〕 AS SETNOCOUNTON; DECLAREsql1VARCHAR(MAX) DECLAREsqlVARCHAR(MAX) DECLAREsql2VARCHAR(MAX) DECLAREIPVARCHAR(MAX) DECLAREDBNameVARCHAR(MAX) DECLAREDataTableVARCHAR(MAX) DECLARETargetIPVARCHAR(MAX) DECLARETargetDBVARCHAR(MAX) DECLARETargetTableVARCHAR(MAX) DECLAREPrerequisiteVARCHAR(MAX) DECLAREDelMaxQTYINT DECLAREStartTimeDATETIME DECLAREEndTimeDATETIME DECLAREqtyINT DECLAREISCHECKORDERIDINT Carson20181217备份数据的时间往往比删除的时间长3倍,因此,如果考虑将备份的操作转移到辅助库,将会对线上的操作影响降至更低 DECLAREBakDateIPVARCHAR(30) setBakDateIP〔XXX。XXX。XXX。XXX〕。后面一定要有一个点 归档操作 DECLAREDBNameCURSOR FOR SELECTIP, DBName, DataTable, TargetIP, TargetDB, TargetTable, Prerequisite, DelMaxQTY, ISCHECKORDERID, StartTime, EndTime FROM〔中央管理器〕。〔中央管理数据库〕。〔dbo〕。〔DBDataArchiveConfig〕 WHEREDataTable ANDTargetTable ANDDBNAMEXXXXXXXXXandSPName????? OPENDBName FETCHNEXTFROMDBNameINTOIP,DBName,DataTable,TargetIP,TargetDB, TargetTable,Prerequisite,DelMaxQTY,ISCHECKORDERID, StartTime,EndTime WHILE(fetchstatus0) BEGIN DECLAREdatetimeDATETIME IFISCHECKORDERID1ANDDataTable BEGIN SETdatetimeCONVERT(VARCHAR(10),GETDATE()30,120) SETsqlInsertinto〔TargetIP〕。 TargetDB。dbo。TargetTable selectFROMBakDateIPDBName。dbo。DataTable with(nolock)wherePrerequisite SETsql1DECLAREicountINTEGER SELECTicountCOUNT(1) FROMBakDateIPDBName。dbo。DataTable wherePrerequisite insertinto〔中央管理器〕。〔中央管理数据库〕。dbo。DBDataArchiveLog(IP,DBName,DataTable,BakQTY,BakStartDate,BakEndDate) selectIP,DBName,DataTable ,icount,getdate(),null WHILEicount0 BEGIN DELETETOP(CAST(DelMaxQTYASVARCHAR(10))) FROMDBName。dbo。DataTable wherePrerequisite SETicounticount( CAST(DelMaxQTYASVARCHAR(10))) WAITFORDELAY00:00:01 END BEGINTRY EXEC(sql) EXEC(sql1) ENDTRY BEGINCATCH DECLAREErrmsgASnvarchar(MAX) SELECTErrmsgERRORMESSAGE() 0001BEGINSAVEERRLOGINTABLE INSERTINTO〔中央管理器〕。〔中央管理数据库〕。〔dbo〕。DBDataArchiveErrLog(〔IP〕,〔DBName〕,〔DataTable〕,〔TargetIP〕,〔TargetDB〕,〔TargetTable〕,〔Errormsg〕,〔TransDateTime〕) VALUES(IP,DBName,DataTable,TargetIP,TargetDB,TargetTable,Errmsg,convert(VARCHAR(25),GETDATE(),120)) 0001END 0002BEGINSENDEMAILMESSAGE DECLARESubjectASnvarchar(200) DECLAREBodyASnvarchar(MAX) DECLARESPNameASnvarchar(MAX) SETSubject数据库归档异常重要!;ServerIP:IPDB:DBName SETSPName SETBodyDearAll,ServerIP:IP;DataBase:DBName上的Table归档异常,请及时检查!!! Youcangetdetailinformationfromthetable。 SETBodyBody SELECTSPNameSPName SETBodyBodySPNameServerIPDBNameTableNameTargetIPTargetDBErrmsgTransDateTimeCAST(IPASNVARCHAR(50))CAST(DBNameASNVARCHAR(50))CAST(DataTableASNVARCHAR(50)) CAST(TargetIPASNVARCHAR(20))CAST(TargetDBASNVARCHAR(50))SUBSTRING(Errmsg,1,100)CONVERT(varchar(100),GETDATE(),21) SETBODYREPLACE(BODY,,) IFREPLACE(BODY,,) BEGIN DECLAREAllEmailToAddressvarchar(3000) DECLAREAllEmailCcAddressvarchar(3000) DECLAREAllprofilenamevarchar(100) SELECTAllEmailToAddress SELECTAllEmailCcAddress SELECTTOP1AllprofilenameNAMEFROMmsdb。dbo。sysmailprofile ORDERBYprofileid EXECmsdb。。spsenddbmailprofilenameAllprofilenameprofile名称 ,recipientsAllEmailToAddress收件人邮箱 ,copyrecipientsAllEmailCcAddress ,subjectSubject邮件标题 ,bodyBODY邮件内容 ,bodyformatHTML邮件格式 ,fileattachments ,ImportanceHigh END 0002end ENDCATCH END FETCHNEXTFROMDBNameINTOIP,DBName,DataTable,TargetIP, TargetDB,TargetTable,Prerequisite,DelMaxQTY, ISCHECKORDERID,StartTime,EndTime END CLOSEDBName DEALLOCATEDBName DECLAREDELETETABLECURSOR FOR SELECTIP, DBName, DataTable, TargetTable, Prerequisite, DelMaxQTY FROM〔中央管理器〕。〔中央管理数据库〕。〔dbo〕。〔DBDataArchiveConfig〕 WHEREDataTable ANDTargetTable ANDDBNAMEXXXXXXXXXandSPName???? OPENDELETETABLE FETCHNEXTFROMDELETETABLEINTOIP,DBName,DataTable, TargetTable,Prerequisite,DelMaxQTY WHILE(fetchstatus0) BEGIN SETsql1DECLAREicountINTEGER SELECTicountCOUNT(1) FROMDBName。dbo。DataTable wherePrerequisite WHILEicount0 BEGIN DELETETOP(CAST(DelMaxQTYASVARCHAR(10))) FROMDBName。dbo。DataTable wherePrerequisite SETicounticount( CAST(DelMaxQTYASVARCHAR(10))) WAITFORDELAY00:00:01 END PRINTsql1 EXEC(sql1) FETCHNEXTFROMDELETETABLEINTOIP,DBName,DataTable,TargetTable,Prerequisite,DelMaxQTY END CLOSEDELETETABLE DEALLOCATEDELETETABLE GO 五。补充数据 1。数据库归档,一般都是先将当前库的历史数据归档到历史库,再将当前库的历史数据删除。这两个阶段,一般是前者耗时较多(一般都在2:1以上),虽然可以在select过程加上nolock,但是或者IO或者网络等原因,其实这个阶段对应用程序的影响还是比较大的。所以,建议将这两个阶段物理分开,即如果有配置AlwaysOn,请将第一个阶段在辅助数据库中执行。上面的SP示例,就是通过参数BakDateIP来实现了这一作用。 2。存储过程中包含了try。。。catch,所以运行此sp就会很少报错,某一个表的异常不会相互影响。例如,我们常见的当前库、历史库由于表结构变更而导致的不一致,此情况出现后,try。。catch可以捕捉到异常,将异常记录在档,并将此信息以邮件的形式发送给指定人,但整个SP不会执行失败。并且还会跳过这一个异常,继续执行下一个备份归档表的归档。 本文版权归作者所有 好文要顶关注我收藏该文 作者:东山絮柳仔 原文:https:www。cnblogs。comxuliuzaip10168858。html