MS SQL 監控磁盤空間告警


        這幾天突然有個想法:希望能夠自動監控、收集數據庫服務器的磁盤容量信息,當達到一個閥值后,自動發送告警郵件給DBA,將數據庫磁盤詳細信息告知DBA,提醒DBA做好存儲規划計划,初步的想法是通過作業調用存儲過程來實現(每天調用一次),這樣避免了我每天每台數據庫服務器都上去檢查一下,尤其是手頭的數據庫服務器N多的情況,這樣可以避免我每天浪費無謂的時間。如果大家有更好的建議和方法,歡迎指點一二,我整理、修改了三個存儲過程如下:

存儲過程1:SP_DiskCapacityAlert1.prc

說明:需要通過調用OLE 自動存儲過程獲取磁盤信息,而這些組件,基於服務器的安全配置,通常是禁用的,我們在存儲過程通過sp_configure開啟這個服務,調用服務完畢后,又通過sp_configure禁用該服務。另外,數據庫服務器都位於內網,因此安全問題應該不大。

USE master;
GO
 
SET ANSI_NULLS ON
GO
 
SET QUOTED_IDENTIFIER ON
GO
 
 
 
IF EXISTS (SELECT 1 FROM dbo.sysobjects WHERE id = OBJECT_ID(N'sp_diskcapacity_alert1') AND OBJECTPROPERTY(id, 'IsProcedure') =1)
    DROP PROCEDURE sp_diskcapacity_alert1;
GO
 
--==================================================================================================================
--        ProcedureName        :            sp_diskcapacity_alert1
--        Author               :            Kerry    
--        CreateDate           :            2013-05-02
--        Description          :            獲取數據庫所在服務器的磁盤容量,當達到閥值是,發送告警郵件,提醒DBA做好存儲規划計划
/******************************************************************************************************************
    Modified Date        Modified User        Version                    Modified Reason
    2013-05-6               Kerry            V01.00.00          修改HTML輸出樣式.以及磁盤容量輸出改為GB
*******************************************************************************************************************/
--==================================================================================================================
CREATE PROCEDURE [dbo].[sp_diskcapacity_alert1]
(
        @Threshold    NUMERIC
)
AS
 
SET NOCOUNT ON
 
 
DECLARE @Result                INT;
DECLARE @objectInfo            INT;
DECLARE @DriveInfo             CHAR(1);
DECLARE @TotalSize             VARCHAR(20);
DECLARE @OutDrive              INT;
DECLARE @UnitMB                BIGINT;
DECLARE @HtmlContent           NVARCHAR(MAX) ; 
DECLARE @FreeRat               NUMERIC;
DECLARE @EmailHead             VARCHAR(120);
SET @UnitMB = 1048576;
 
 
 
 
--創建臨時表保存服務器磁盤容量信息
CREATE TABLE #DiskCapacity
(
    [DiskCD]        CHAR(1) ,
    FreeSize        INT        ,
    TotalSize       INT        
);
 
INSERT #DiskCapacity
        ([DiskCD], FreeSize ) 
EXEC master.dbo.xp_fixeddrives;
 
EXEC sp_configure 'show advanced options', 1
RECONFIGURE WITH OVERRIDE;
 
EXEC sp_configure 'Ole Automation Procedures', 1;
RECONFIGURE WITH OVERRIDE;
 
 
EXEC @Result = master.sys.sp_OACreate 'Scripting.FileSystemObject',@objectInfo OUT;
 
DECLARE CR_DiskInfo CURSOR LOCAL FAST_FORWARD
FOR SELECT  DiskCD FROM #DiskCapacity
ORDER by DiskCD
 
OPEN CR_DiskInfo;
 
FETCH NEXT FROM CR_DiskInfo INTO @DriveInfo
 
WHILE @@FETCH_STATUS=0
BEGIN
 
    EXEC @Result = sp_OAMethod @objectInfo,'GetDrive', @OutDrive OUT, @DriveInfo
 
 
    EXEC @Result = sp_OAGetProperty @OutDrive,'TotalSize', @TotalSize OUT
 
 
    UPDATE #DiskCapacity
    SET TotalSize=@TotalSize/@UnitMB
    WHERE DiskCD=@DriveInfo
 
    FETCH NEXT FROM CR_DiskInfo INTO @DriveInfo
 
END
 
CLOSE CR_DiskInfo
DEALLOCATE CR_DiskInfo;
 
EXEC @Result=sp_OADestroy @objectInfo
 
EXEC sp_configure 'show advanced options', 1
RECONFIGURE WITH OVERRIDE;
 
EXEC sp_configure 'Ole Automation Procedures', 0;
RECONFIGURE WITH OVERRIDE;
 
EXEC sp_configure 'show advanced options', 0
RECONFIGURE WITH OVERRIDE;
 
SELECT @FreeRat =FreeRate
FROM (
        SELECT ROW_NUMBER() OVER (ORDER BY FreeSize / ( TotalSize * 1.0 ) ASC) AS RowIndex,
               CAST(( FreeSize / ( TotalSize * 1.0 ) ) * 100.0 AS INT)          AS FreeRate  
             
        FROM    #DiskCapacity
     ) T
WHERE RowIndex = 1;
 
    IF @FreeRat <= @Threshold
        BEGIN
        
        IF @FreeRat > 10 AND @FreeRat <=20 
            SET @EmailHead ='數據庫磁盤容量告警(告警級別3)'
        ELSE IF @FreeRat >=5 AND @FreeRat <=10
            SET @EmailHead ='數據庫磁盤容量告警(告警級別4)'
        ELSE
            SET @EmailHead ='數據庫磁盤容量告警(告警級別5)'
        
        SET @HtmlContent =
            +   N'<html>'
            +   N'<style type="text/css">'
            +   N' td {border:solid #9ec9ec;  border-width:0px 1px 1px 0px; padding:4px 0px;}'
            +   N' table {border:1px solid #9ec9ec; width:100%;border-width:1px 0px 0px 1px;text-align:center;font-size:12px}'
            +   N'</style>'
            +   N'<H1 style="color:#FF0000; text-align:center;font-size:14px">' + @EmailHead +'</H1>'    
            +   N'<table  >'    
            +   N'<tr><th>磁盤盤符</th><th>總大小(GB)</th><th>已用空間(GB)</th><th>剩余空間(GB)</th>'     
            +   N'<th>已用比例(%)</th><th>剩余比例(%)</th></tr >' +    
            CAST ( ( SELECT 
            td =  DiskCD                                                , '',
            td = STR(TotalSize*1.0/1024,6,2)                            , '',  
            td = STR((TotalSize - FreeSize)*1.0/1024,6,2)               , '',                          
            td = STR(FreeSize*1.0/1024,6,2)                             , '',    
            td = STR(( TotalSize - FreeSize)*1.0/(TotalSize)* 100.0,6,2), '',         
            td = STR(( FreeSize * 1.0/ ( TotalSize  ) ) * 100.0,6,2)    , ''              
            FROM #DiskCapacity
            FOR XML PATH('tr'), TYPE     ) AS NVARCHAR(MAX) ) +     N'</table></html>' ; 
            
         
            
         EXEC msdb.dbo.sp_send_dbmail     
            @profile_name = 'DataBase_DDL_Event',    --指定你自己的profile_name    
            @recipients='****@163.com',                --指定你要發送到的郵箱
            @subject = '服務器磁盤空間告警',     
            @body = @HtmlContent,   
            @body_format = 'HTML' ; 
        END
 
    
DROP TABLE #DiskCapacity;
 
RETURN;
 
GO
 
 

存儲過程2:SP_DiskCapacityAlert2.prc

說明:需要啟用xp_cmdshell來獲取磁盤信息,關於xp_cmdshell安全隱患,一般該功能都是禁用的。

USE [master]
GO
 
 
SET ANSI_NULLS ON
GO
 
SET QUOTED_IDENTIFIER ON
GO
 
IF OBJECT_ID(N'dbo.sp_diskcapacity_alert2') IS NOT NULL
    DROP PROCEDURE dbo.sp_diskcapacity_alert2;
 
GO
 
--==================================================================================================================
--        ProcedureName        :            sp_diskcapacity_alert2
--        Author               :            Kerry    
--        CreateDate           :            2013-05-02
--        Description          :            獲取數據庫所在服務器的磁盤容量,當達到閥值時,發送告警郵件,提醒DBA做好存儲規划計划
/******************************************************************************************************************
    Modified Date        Modified User        Version                    Modified Reason
    2013-05-6             Kerry                 V01.00.00                修改HTML輸出樣式.以及磁盤容量輸出改為GB
*******************************************************************************************************************/
--==================================================================================================================
CREATE PROCEDURE [dbo].[sp_diskcapacity_alert2]
(
        @Threshold    NUMERIC
)
    
AS 
BEGIN
    
SET NOCOUNT ON;
 
DECLARE @HtmlContent    NVARCHAR(MAX) ; 
DECLARE @FreeRat        NUMERIC;
DECLARE @EmailHead        VARCHAR(200);
 
--創建臨時表保存服務器磁盤容量信息
CREATE TABLE #DiskCapacity
(
    DiskCD            CHAR(4) ,
    FreeSize         INT        ,
    TotalSize         BIGINT        
);
 
INSERT INTO #DiskCapacity
        ( DiskCD, FreeSize )
EXEC master..xp_fixeddrives;
 
 
 
EXEC sp_configure 'show advanced options', 1
RECONFIGURE
EXEC sp_configure 'xp_cmdshell', 1
RECONFIGURE
EXEC sp_configure 'show advanced options', 0
RECONFIGURE
 
 
CREATE TABLE #DriveInfo1(ID INT IDENTITY(1,1),DiskCD VARCHAR(12));
 
INSERT INTO #DriveInfo1(DiskCD)
EXEC xp_cmdshell 'wmic LOGICALDISK get name';
 
 
CREATE TABLE #DriveInfo2(ID INT IDENTITY(1,1), TotalSize VARCHAR(22));
 
INSERT INTO #DriveInfo2
        ( TotalSize )
EXEC  xp_cmdshell 'wmic LOGICALDISK get size';
 
  
DELETE FROM #DriveInfo1 WHERE ID=1;
DELETE FROM #DriveInfo2 WHERE ID=1;
 
  
UPDATE #DriveInfo1 SET DiskCD = REPLACE(DiskCD,':','');
SELECT * FROM #DiskCapacity
 
UPDATE #DiskCapacity  SET TotalSize =(SELECT CAST(LEFT(N.TotalSize, LEN(N.TotalSize)-1) AS BIGINT)/1024/1024 FROM #DriveInfo1 M INNER JOIN #DriveInfo2 N ON M.ID = N.ID
WHERE M.DiskCD IS NOT NULL AND LEN(M.DiskCD) >1 AND #DiskCapacity.DiskCD = LEFT(M.DiskCD, LEN(M.DiskCD)-1))
  
  SELECT * FROM #DiskCapacity
  
EXEC sp_configure 'show advanced options', 1
RECONFIGURE
EXEC sp_configure 'xp_cmdshell', 0
RECONFIGURE
EXEC sp_configure 'show advanced options', 0
RECONFIGURE
 
SELECT @FreeRat =FreeRate
FROM (
        SELECT ROW_NUMBER() OVER (ORDER BY FreeSize / ( TotalSize * 1.0 ) ASC) AS RowIndex,
               CAST(( FreeSize / ( TotalSize * 1.0 ) ) * 100.0 AS INT)     AS FreeRate  
             
        FROM    #DiskCapacity
     ) T
WHERE RowIndex = 1;
 
    IF @FreeRat <= @Threshold
        BEGIN
        
        IF @FreeRat > 10 AND @FreeRat <=20 
            SET @EmailHead ='數據庫磁盤容量告警(告警級別3)'
        ELSE IF @FreeRat >=5 AND @FreeRat <=10
            SET @EmailHead ='數據庫磁盤容量告警(告警級別4)'
        ELSE
            SET @EmailHead ='數據庫磁盤容量告警(告警級別5)'
        
        SET @HtmlContent =
            +   N'<html>'
            +   N'<style type="text/css">'
            +   N' td {border:solid #9ec9ec;  border-width:0px 1px 1px 0px; padding:4px 0px;}'
            +   N' table {border:1px solid #9ec9ec; width:100%;border-width:1px 0px 0px 1px;text-align:center;font-size:12px}'
            +   N'</style>'
            +   N'<H1 style="color:#FF0000; text-align:center;font-size:14px">' + @EmailHead +'</H1>'    
            +   N'<table  >'    
            +   N'<tr><th>磁盤盤符</th><th>總大小(GB)</th><th>已用空間(GB)</th><th>剩余空間(GB)</th>'     
            +   N'<th>已用比例(%)</th><th>剩余比例(%)</th></tr >' +    
            CAST ( ( SELECT 
            td =  DiskCD                                                , '',
            td = STR(TotalSize*1.0/1024,6,2)                            , '',  
            td = STR((TotalSize - FreeSize)*1.0/1024,6,2)               , '',                          
            td = STR(FreeSize*1.0/1024,6,2)                             , '',    
            td = STR(( TotalSize - FreeSize)*1.0/(TotalSize)* 100.0,6,2), '',         
            td = STR(( FreeSize * 1.0/ ( TotalSize  ) ) * 100.0,6,2)    , ''              
            FROM #DiskCapacity
            FOR XML PATH('tr'), TYPE     ) AS NVARCHAR(MAX) ) +     N'</table></html>' ; 
            
         
            
         EXEC msdb.dbo.sp_send_dbmail     
            @profile_name = 'DataBase_DDL_Event', --指定你自己的profile_name       
            @recipients='konglb@***.com',         --指定你要發送到的郵箱
            @subject = '服務器磁盤空間告警',     
            @body = @HtmlContent,   
            @body_format = 'HTML' ; 
        END
 
END 
 
GO

存儲過程3:SP_DiskCapacityAlert2.prc

說明:這個存儲過程不用上面兩個有安全隱患的存儲過程,但是獲取不到磁盤的總體信息,就不能通過一個閥值來告警,只能設置當磁盤剩余多少空間時,產生告警郵件。

USE [master]
GO
 
 
SET ANSI_NULLS ON
GO
 
SET QUOTED_IDENTIFIER ON
GO
 
IF OBJECT_ID(N'dbo.sp_diskcapacity_alert3') IS NOT NULL
    DROP PROCEDURE dbo.sp_diskcapacity_alert3;
 
GO
 
--==================================================================================================================
--        ProcedureName        :            sp_diskcapacity_alert3
--        Author               :            Kerry    
--        CreateDate           :            2013-05-02
--        Description          :            獲取數據庫所在服務器的磁盤容量,當某個磁盤剩余容量低於某個值時,發送告警郵件,
--                                          提醒DBA做好存儲規划計划
/******************************************************************************************************************
    Modified Date        Modified User        Version                    Modified Reason
    2013-05-6                Kerry          V01.00.00           修改HTML輸出樣式.以及磁盤容量輸出改為GB
*******************************************************************************************************************/
--==================================================================================================================
CREATE PROCEDURE [dbo].[sp_diskcapacity_alert3]
(
        @DiskCapacity    FLOAT
)
    
AS 
BEGIN
 
DECLARE @FreeSize         INT;
DECLARE @EmailHead        VARCHAR(200);
DECLARE @HtmlContent      NVARCHAR(MAX) ; 
 
 
--創建臨時表保存服務器磁盤容量信息
CREATE TABLE #DiskCapacity
(
    DiskCD            CHAR(4) ,
    FreeSize        INT            
);
 
INSERT INTO #DiskCapacity
        ( DiskCD, FreeSize )
EXEC master..xp_fixeddrives;
 
SELECT  @FreeSize = FreeSize*1.0/1024
FROM    ( SELECT    ROW_NUMBER() OVER ( ORDER BY FreeSize ASC ) AS RowIndex ,
                    FreeSize AS FreeSize
          FROM      #DiskCapacity
        ) T
WHERE   RowIndex = 1 ;
 
SELECT FreeSize*1.0/1024 FROM  #DiskCapacity;
  IF @FreeSize <= @DiskCapacity 
    BEGIN
        
        IF @FreeSize > 1
            AND @FreeSize <= 2 
            SET @EmailHead = '數據庫磁盤容量告警(告警級別3)'
        ELSE 
            IF @FreeSize >= 0.5
                AND @FreeSize <= 1 
                SET @EmailHead = '數據庫磁盤容量告警(告警級別4)'
            ELSE 
                SET @EmailHead = '數據庫磁盤容量告警(告警級別5)'
        
        SET @HtmlContent = +N'<html>' + N'<style type="text/css">'
            + N' td {border:solid #9ec9ec;  border-width:0px 1px 1px 0px; padding:4px 0px;}'
            + N' table {border:1px solid #9ec9ec; width:100%;border-width:1px 0px 0px 1px;text-align:center;font-size:12px}'
            + N'</style>'
            + N'<H1 style="color:#FF0000; text-align:center;font-size:14px">'
            + @EmailHead + '</H1>' + N'<table  >'
            + N'<tr><th>磁盤盤符</th><th>剩余空間(GB)</th>' + N'</tr >'
            + CAST(( SELECT td = DiskCD ,
                            '' ,
                            td = STR(FreeSize * 1.0 / 1024, 6, 2) ,
                            ''
                     FROM   #DiskCapacity
                   FOR
                     XML PATH('tr') ,
                         TYPE
                   ) AS NVARCHAR(MAX)) + N'</table></html>' ; 
                   
           EXEC msdb.dbo.sp_send_dbmail     
            @profile_name = 'DataBase_DDL_Event',  --指定你自己的profile_name   
            @recipients='konglb@***.com',          --指定你要發送到的郵箱
              @subject = '服務器磁盤空間告警',     
            @body = @HtmlContent,   
            @body_format = 'HTML' ; 
            
    END
 
END
GO


免責聲明!

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



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