SQLSERVER--定期清理維護作業的歷史記錄


剛刪除一個數據庫時,在清理數據庫備份歷史記錄時,執行超過近10分鍾還未完成,隨時查了下,嚇死寶寶啦,邏輯讀操作竟然高達8000萬次以上!

通過UI進行刪除數據庫時,會默認勾選上“刪除數據庫備份和還原歷史記錄信息”,作為多年的老司機,刪除數據庫應該寫腳本進行刪除,即使使用UI刪除,也應該不勾選該選項,但一時偷懶,直接點執行,導致該操作消耗大量邏輯IO和CPU並持續10分鍾還不能成功完成。

勾選上“刪除數據庫備份和還原歷史記錄信息”后,會執行下面語句:

EXEC msdb.dbo.sp_delete_database_backuphistory @database_name = N'monitor'
GO

執行該存儲過程后,會在msdb數據庫中嵌套地刪除備份相關的N張表,其中一條刪除語句如下:

 DELETE msdb.dbo.backupmediafamily
 FROM   msdb.dbo.backupmediafamily bmf
 WHERE  bmf.media_set_id IN ( SELECT    media_set_id
                              FROM      @media_set_id )
        AND ( ( SELECT  COUNT(*)
                FROM    msdb.dbo.backupset
                WHERE   media_set_id = bmf.media_set_id
              ) = 0 )

當備份和還原歷史記錄信息較多的時候,刪除操作消耗的資源會成幾何數增長,由於該服務器用作日志傳送服務器,承載很多個數據庫的日志傳送,因此相關備份表中存有大量數據,導致刪除操作長時間不能完成。

 

解決辦法:

定期執行下面腳本來清理備份還原數據:

--設置歷史記錄保存期限為1天
DECLARE @keepMinutes BIGINT
SET @keepMinutes= 60*24

DECLARE @expiredDT NVARCHAR(100)
SELECT  @expiredDT = dbo.ufn_FormatDate(DATEADD(MINUTE, 0 - @keepMinutes,
                                                GETDATE()),
                                        'yyyy-MM-ddTHH:mm:ss')


EXEC msdb.dbo.sp_delete_backuphistory @expiredDT

EXEC msdb.dbo.sp_purge_jobhistory @oldest_date = @expiredDT

EXEC msdb.dbo.sp_maintplan_delete_log NULL, NULL, @expiredDT

上面腳本中使用到一個日期格式轉換函數,代碼為:

/****** Object:  UserDefinedFunction [dbo].[ufn_FormatDate]    Script Date: 2015/11/24 19:40:45 ******/
DROP FUNCTION [dbo].[ufn_FormatDate]
GO


/****** Object:  UserDefinedFunction [dbo].[ufn_FormatDate]    Script Date: 2015/11/24 19:40:45 ******/
SET ANSI_NULLS ON
GO


SET QUOTED_IDENTIFIER ON
GO


--====================================
--將時間轉換成制定格式的字符串
CREATE FUNCTION [dbo].[ufn_FormatDate]
   (
     @Datetime DATETIME ,
     @FormatMask VARCHAR(32)
   )
RETURNS VARCHAR(32)
AS
   BEGIN


       DECLARE @StringDate VARCHAR(32)


       SET @StringDate = @FormatMask


       IF ( CHARINDEX('YYYY', @StringDate) > 0 )
           SET @StringDate = REPLACE(@StringDate, 'YYYY',
                                     DATENAME(YY, @Datetime))


       IF ( CHARINDEX('YY', @StringDate) > 0 )
           SET @StringDate = REPLACE(@StringDate, 'YY',
                                     RIGHT(DATENAME(YY, @Datetime), 2))
       IF ( CHARINDEX('MM', @StringDate) > 0 )
           SET @StringDate = REPLACE(@StringDate, 'MM',
                                     RIGHT('0' + CONVERT(VARCHAR, DATEPART(MM,
                                                             @Datetime)), 2))




       IF ( CHARINDEX('DD', @StringDate) > 0 )
           SET @StringDate = REPLACE(@StringDate, 'DD',
                                     RIGHT('0' + DATENAME(DD, @Datetime), 2))




       IF ( CHARINDEX('HH', @StringDate) > 0 )
           SET @StringDate = REPLACE(@StringDate, 'HH',
                                     RIGHT('0' + DATENAME(HH, @Datetime), 2))


       IF ( CHARINDEX('mm', @StringDate) > 0 )
           SET @StringDate = REPLACE(@StringDate, 'mm',
                                     RIGHT('0' + DATENAME(mm, @Datetime), 2))


       IF ( CHARINDEX('ss', @StringDate) > 0 )
           SET @StringDate = REPLACE(@StringDate, 'ss',
                                     RIGHT('0' + DATENAME(ss, @Datetime), 2))


       IF ( CHARINDEX('ms', @StringDate) > 0 )
           SET @StringDate = REPLACE(@StringDate, 'ms',
                                     RIGHT('0' + DATENAME(ms, @Datetime), 2))


       RETURN @StringDate


   END
--====================================


GO
View Code


沒多少技術含量,厚臉拿出來供初學者學習下!

============================================

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM