监视SQL Server数据文件中的可用空间


9

我已手动将mdf / ndf文件调整为较大的大小,以避免在SQL Server数据库上进行自动增长操作。由于文件较大,因此磁盘分区上的可用空间非常小,系统管理员不断提醒我空间不足。

由于我调整了它们的大小,因此数据文件中有很多可用空间,但是从文件大小/磁盘可用空间来看,人们不会注意到它。

如何监视数据文件的实际使用百分比?我更喜欢使用perfmon计数器。我很担心,当文件真正用完空间时,SQL Server将无法分配足够的空间,并且将崩溃。

Answers:


11

不确定从简单查询中获取性能计数器时为什么要使用性能计数器。实际上,尽管您可以从性能计数器(Log File(s) Size (KB)/ Log File(s) Used Size (KB))获取有关日志文件的信息,但是没有这样的计数器可以统计数据文件中使用了多少空间。

;WITH f AS 
(
  SELECT name, size = size/128.0 FROM sys.database_files
),
s AS
(
  SELECT name, size, free = size-CONVERT(INT,FILEPROPERTY(name,'SpaceUsed'))/128.0
  FROM f
)
SELECT name, size, free, percent_free = free * 100.0 / size
FROM s;

我希望它可以在不使用SQL Server的情况下完成。当然,我可以手动查询并查看可用空间,但是我需要一个自动化的解决方案。性能计数器非常理想,因为系统管理员可以将其与监视软件一起使用。我可能会使用您的查询并设置一个SQL Agent作业+电子邮件警报。另外,我将尝试Kin的解决方案,看看哪种方法效果最好。
BuahahaXD 2015年

1
我有一个类似的用例。如果现成的监视解决方案不是特定于SQL Server的,而是了解Windows,那么性能计数器将更易于实现和监视。
Michael J Swart '18年

7

我有另一种方法可以主动监视数据文件空间,并使用SQL Alert来警告可用空间是否低于某个百分比。

基础是

  • 在sys.messages中创建用户定义的错误消息。这将由sql代理警报使用。

    -- User-defined error messages can be an integer between 50001 and 2147483647. 
    EXEC sp_addmessage 
      @msgnum=911421, -- 911DBA
      @severity=1,    -- Informational message not generated by DB Engine       
      @msgtext=N'Data files are %d percent full in database %s.'
    
  • 现在创建一个SQL Agent作业。确保set @threshold = 20 --->>>>>>>>>>>>>>>>> CHANGE HERE <<<<<<<<<<<<<<<<<<<<<---在以下脚本中进行更改。我把他的门槛设置得很低,只是为了模拟警报。安排作业每30分钟运行一次(根据您的需要进行更改)。

        if object_id('tempdb..#dbserversize') is not null
        DROP TABLE #dbserversize;
    
        create table dbo.#dbserversize (
         [id] int identity (1,1)
         ,[databaseName] sysname
        ,[Drive]    varchar(3)
        ,[Logical Name] sysname
        ,[Physical Name]    varchar(max)
        ,[File Size MB] decimal(38, 2)
        ,[Space Used MB]    decimal(38, 2)
        ,[Free Space]   decimal(38, 2)
        ,[%Free Space]  decimal(38, 2)
        ,[Max Size] varchar(max)
        ,[Growth Rate]  varchar(max)
        )
    
        declare @id int
        declare @threshold int
        declare @dbname sysname
    
        declare @sqltext nvarchar(max)
    
        declare @freespacePct int
    
        set @threshold = 20   --->>>>>>>>>>>>>>>>> CHANGE HERE <<<<<<<<<<<<<<<<<<<<<---
    
        select @dbname = min(name) from sys.databases where database_id > 4 and [state] = 0 
    
        while @dbname is not NULL
    
        begin
            select @dbname = name from sys.databases where name = @dbname and database_id > 4 and [state] = 0 
                --- Modified from Erin's blog : Proactive SQL Server Health Checks, Part 1 : Disk Space
                --- source http://sqlperformance.com/2014/12/io-subsystem/proactive-sql-server-health-checks-1
            set @sqltext =  ' use '+@dbname+';'+' 
                insert into dbo.#dbserversize
                select '''+@dbname+''' as [databaseName]
                    ,substring([physical_name], 1, 3) as [Drive]
                    ,[name] as [Logical Name]
                    ,[physical_name] as [Physical Name]
                    ,cast(CAST([size] as decimal(38, 2)) / 128.0 as decimal(38, 2)) as [File Size MB]
                    ,cast(CAST(FILEPROPERTY([name], ''SpaceUsed'') as decimal(38, 2)) / 128.0 as decimal(38, 2)) as [Space Used MB]
                    ,cast((CAST([size] as decimal(38, 0)) / 128) - (CAST(FILEPROPERTY([name], ''SpaceUsed'') as decimal(38, 0)) / 128.) as decimal(38, 2)) as [Free Space]
                    ,cast(((CAST([size] as decimal(38, 2)) / 128) - (CAST(FILEPROPERTY([name], ''SpaceUsed'') as decimal(38, 2)) / 128.0)) * 100.0 / (CAST([size] as decimal(38, 2)) / 128) as decimal(38, 2)) as [%Free Space]
                    ,case 
                        when cast([max_size] as varchar(max)) = - 1
                            then ''UNLIMITED''
                        else cast([max_size] as varchar(max))
                        end as [Max Size]
                    ,case 
                        when is_percent_growth = 1
                            then cast([growth] as varchar(20)) + ''%''
                        else cast([growth] as varchar(20)) + ''MB''
                        end as [Growth Rate]
                    from sys.database_files
                    where type = 0 -- for Rows , 1 = LOG'
                --print @sqltext
                exec (@sqltext)
    
    
                select @dbname = min(name) from sys.databases where name > @dbname and database_id > 4 and [state] = 0 
        end
    
    
        --- delete the entries that do not meet the threshold 
    
        delete from dbo.#dbserversize
        where [%Free Space] < @threshold;
    
    
        --select * from dbo.#dbserversize
    
        --- NOW Raise errors for the databases that we got flagged up
    
        while exists (select null from dbo.#dbserversize)
        begin
    
            select top 1 @id = id,
                        @dbname = databaseName,
                        @freespacePct = [%Free Space]
                    from dbo.#dbserversize;
    
    
                RAISERROR(911421, 10,1,@freespacePct, @dbname) with LOG;
    
                delete from dbo.#dbserversize where id = @id;
    
        end
    
  • 现在创建警报以响应911421错误号。

    USE [msdb]
    GO
    EXEC msdb.dbo.sp_add_alert @name=N'MDF file alert', 
            @message_id=911421, 
            @severity=0, 
            @enabled=1, 
            @delay_between_responses=1800, 
            @include_event_description_in=0, 
            @job_id=N'019c4770-865b-406b-894e-72a1ff34f732'
    GO
    EXEC msdb.dbo.sp_add_notification @alert_name=N'MDF file alert', @operator_name=N'Notify 911 DBA for MDF files getting full', @notification_method = 1
    GO
    

    在此处输入图片说明

    在此处输入图片说明

注意:您可以使用上述我的想法进行其他类型的增强。

  • 使代理作业作为接受阈值作为输入值的存储过程。
  • 将值记录到DBA数据库中的物理表中,以便进行趋势分析和容量规划。
  • 您能想到的任何其他.... :-)

您的查询有问题。我认为某个地方存在无限循环。我配置了警报,关闭了警报触发的作业,并且不断收到大量有关数据文件的邮件:)
BuahahaXD 2015年

1
您应该使用两次响应之间的延迟设置。
Kin Shah

5

只是基于Aaron和Kin的答案,您可以使用perf计数器来实现,但是可以使用用户可设置的计数器之一

我会:

  • 创建一个存储过程,该存储过程将使用Aaron的查询来获取单个文件中的可用空间或遍历所有文件,并获得感兴趣的最小/最大值
  • 创建一个将定期运行存储的过程的作业

如果您想得到适当的通知:

  • 创建操作员/使用具有有效电子邮件地址的现有操作员
  • 根据该用户计数器创建一个警报,该警报将通知前一个操作员(确保您不会被电子邮件淹没-设置两次响应之间的延迟)。

注意事项是:

  • 您只有10个可设置的计数器
  • 他们没有一个有意义的名字
  • 您需要繁琐的工作+ proc +提醒才能拥有一张漂亮的照片

但是它们可以在Perfmon或其他类似工具中使用。


3

另外,还有一个简单的警报设置可以监视数据文件大小:

在此处输入图片说明

附加的“低日志空间警报”将监视事务日志文件的可用空间(自动增长已关闭):

在此处输入图片说明

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.