Surveillance de l'espace libre dans les fichiers de données SQL Server

9

J'ai redimensionné manuellement les fichiers mdf / ndf à une grande taille pour éviter les opérations de croissance automatique sur les bases de données SQL Server. Comme les fichiers sont plus volumineux, il y a très peu d'espace libre sur les partitions de disque et les administrateurs système continuent de m'alerter que je manque d'espace.

Parce que je les ai redimensionnés, il y a beaucoup d'espace libre dans les fichiers de données mais on ne peut pas le remarquer en regardant la taille des fichiers / l'espace libre sur le disque.

Comment puis-je surveiller le% réel d'utilisation des fichiers de données? Je préférerais utiliser des compteurs perfmon. Je suis préoccupé par le fait que lorsque le fichier manque vraiment d'espace, SQL Server ne pourra pas allouer suffisamment d'espace et plantera.

BuahahaXD
la source

Réponses:

11

Vous ne savez pas pourquoi vous souhaitez utiliser des compteurs de performances pour cela lorsque vous pouvez l'obtenir à partir d'une simple requête. Et en fait, bien que vous puissiez obtenir ces informations sur les fichiers journaux à partir des compteurs de performances ( Log File(s) Size (KB)/ Log File(s) Used Size (KB)), il n'existe aucun compteur de ce type pour l'espace utilisé dans un fichier de données.

;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;
Aaron Bertrand
la source
J'espérais que cela pourrait être fait sans utiliser SQL Server. Bien sûr, je peux l'interroger manuellement et voir l'espace libre, mais j'ai besoin d'une solution automatisée. Un compteur perfmon serait parfait car les administrateurs système pourraient l'utiliser avec leur logiciel de surveillance. Je pourrais utiliser votre requête et configurer une tâche SQL Agent + une alerte par e-mail. Je vais également essayer la solution de Kin et voir laquelle fonctionne le mieux.
BuahahaXD
1
J'ai un cas d'utilisation similaire. Si une solution de surveillance standard n'est pas spécifique à SQL Server, mais connaît Windows, un compteur de performances serait plus facile à implémenter et à surveiller.
Michael J Swart
7

J'ai une autre méthode pour surveiller proactivement l'espace des fichiers de données et alerter si l'espace libre tombe en dessous d'un certain pourcentage à l'aide de SQL Alert.

Les bases sont

  • Créez un message d'erreur défini par l'utilisateur dans sys.messages. Cela sera utilisé par l'alerte de l'agent 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.'
  • Créez maintenant un travail SQL Agent. Assurez-vous de changer set @threshold = 20 --->>>>>>>>>>>>>>>>> CHANGE HERE <<<<<<<<<<<<<<<<<<<<<---dans le script ci-dessous. J'ai mis le sien comme un seuil très bas, uniquement pour simuler l'alerte. Planifiez l'exécution du travail toutes les 30 minutes (modifiez-la selon vos besoins).

        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
  • Créez maintenant une alerte pour répondre au 911421numéro d'erreur.

    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

    entrez la description de l'image ici

    entrez la description de l'image ici

Remarque: Il existe d'autres types d'améliorations que vous pouvez faire avec mon idée ci-dessus.

  • Faites de la tâche d'agent une procédure stockée acceptant le seuil comme valeur d'entrée.
  • Consignez les valeurs dans une table physique de la base de données DBA afin de pouvoir analyser les tendances et planifier la capacité.
  • Tout autre que vous pouvez penser .... :-)
Kin Shah
la source
Il y a un problème avec votre requête. Je pense qu'il y a une boucle infinie quelque part. J'ai configuré les alertes, désactivé le déclenchement du travail par l'alerte et je reçois des tonnes de mails sur les fichiers de données :)
BuahahaXD
1
Vous devez utiliser le délai entre les réponses.
Kin Shah
5

Juste pour s'appuyer sur les réponses d'Aaron et de Kin, vous pouvez le faire avec des compteurs de perf, mais l'un des compteurs configurables par l' utilisateur .

Je voudrais:

  • créer une procédure stockée qui utilisera la requête d'Aaron pour obtenir l'espace libre dans un seul fichier ou parcourir tous les fichiers et obtenir la valeur min / max qui vous intéresse
  • créer un travail qui exécutera périodiquement le proc stocké

Si vous souhaitez être correctement informé:

  • créer un opérateur / utiliser un opérateur existant avec une adresse e-mail valide
  • créer une alerte basée sur ce compteur d'utilisateurs qui avertira l'opérateur précédent (assurez-vous de ne pas vous inonder d'e-mails - définissez un délai entre les réponses).

Les mises en garde sont les suivantes:

  • vous n'avez que 10 compteurs réglables
  • ils n'ont pas de nom significatif
  • vous devez avoir le travail encombrant + proc + alerte pour avoir une belle photo

Mais ils peuvent être utilisés dans Perfmon ou un autre outil similaire.

Marian
la source
3

Il existe également des paramètres d'alerte simples pour surveiller la taille du fichier de données:

entrez la description de l'image ici

L'alerte supplémentaire «Low Log Space Alert» surveillera l'espace libre pour le fichier journal des transactions (la croissance automatique est désactivée):

entrez la description de l'image ici

Vladislav
la source