欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

mssql 监控磁盘空间告警实现方法

程序员文章站 2023-02-19 23:43:10
这几天突然有个想法:希望能够自动监控、收集数据库服务器的磁盘容量信息,当达到一个阀值后,自动发送告警邮件给dba,将数据库磁盘详细信息告知dba,提醒dba做好存储规划计划...

这几天突然有个想法:希望能够自动监控、收集数据库服务器的磁盘容量信息,当达到一个阀值后,自动发送告警邮件给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_diskcapacityalert3.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

作者:潇湘隐者
出处:http://www.cnblogs.com/kerrycode/