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

Bua*_*aXD 9 monitoring sql-server perfmon disk-space

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

因为我调整了它们的大小,所以数据文件中有很多可用空间,但在查看文件大小/磁盘可用空间时不会注意到它。

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

Aar*_*and 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;
Run Code Online (Sandbox Code Playgroud)


Kin*_*hah 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.'
    
    Run Code Online (Sandbox Code Playgroud)
  • 现在创建一个 SQL 代理作业。确保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
    
    Run Code Online (Sandbox Code Playgroud)
  • 现在创建一个警报来响应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
    
    Run Code Online (Sandbox Code Playgroud)

    在此处输入图片说明

    在此处输入图片说明

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

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


Mar*_*ian 5

只是为了建立在 Aaron 和 Kin 的答案的基础上,您可以使用 perf counters 但用户可设置的 counters 之一

我会:

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

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

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

警告是:

  • 你只有 10 个可设置的计数器
  • 他们没有有意义的名字
  • 你需要有繁琐的工作+过程+警报才能有一张漂亮的照片

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