web-dev-qa-db-fra.com

Consommation de mémoire de SQL Server 2012 en dehors du pool de mémoire tampon

J'ai une instance de SQL Server 2012 SP2 Enterprise Edition consommant ~ 20 Go de mémoire au-dessus du maximum. limite de mémoire. L'instance est limitée à 65 Go mais la mémoire physique utilisée à partir de la requête ci-dessous affiche 86 Go

SELECT (physical_memory_in_use_kb/1024)/1024 AS [PhysicalMemInUseGB]
FROM sys.dm_os_process_memory;
GO

Le serveur est physique avec 2 nœuds NUMA. Existe-t-il un moyen de savoir ce qui consomme la mémoire en dehors du pool de tampons (je suppose que c'est ce qui se passe)?

Voici la sortie de DBCC MEMORYSTATUS: -

output of DBCC MEMORYSTATUS

Et voici la limite de mémoire définie: -

screen shot of memory limit

Merci d'avance.

MISE À JOUR: - J'ai exécuté la requête suggérée par Aaron

SELECT TOP (20) * FROM sys.dm_os_memory_clerks ORDER BY pages_kb DESC

Voici la sortie: -

MemoryClerkOutput

La somme de pages_kb atteint ~ 60 Go

MISE À JOUR 2: - La sortie complète de DBCC MEMORYSTATUS est ici: - http://Pastebin.com/nGn6kXEc

MISE À JOUR 3: - Sortie des scripts de Shanky dans un fichier Excel ici: - http://jmp.sh/LKRlH4K

MISE À JOUR 4: - Capture d'écran de la sortie de: -

SELECT (physical_memory_in_use_kb/1024)/1024 AS [PhysicalMemInUseGB]
FROM sys.dm_os_process_memory;
GO

PhysMemInUse Screenshot

Cela semble donc indiquer que SQL Server utilise plus que l'ensemble de 65 Go.

9
dbafromthecold

La mémoire maximale du serveur contrôle le pool de mémoire tampon et toutes les allocations de taille de page, mais ne contrôle toujours pas les éléments tels que les allocations Windows directes (serveurs liés, sp_OA, XP)), la mémoire requise pour les threads/piles de threads, etc. .

Vous pouvez probablement vous attendre à ce que cela soit plus élevé sur NUMA (même si je ne suis pas sûr que 20 Go soient normaux); le fait est que vous ne pouvez pas vous attendre à ce que la mémoire maximale du serveur contrôle entièrement la mémoire utilisée par une instance de SQL Server. Si vous souhaitez que l'instance entière (pas seulement le pool de mémoire tampon, les caches de plan et CLR) n'utilise pas plus de 64 Go, vous devez définir la mémoire maximale du serveur sur quelque chose de plus bas.

Quelques idées potentielles pour retrouver cela (je normaliserai tout en Mo):

  • compteurs de performance

    Voyez si quelque chose saute ici comme excessivement grand:

    SELECT counter_name, instance_name, mb = cntr_value/1024.0
      FROM sys.dm_os_performance_counters 
      WHERE (counter_name = N'Cursor memory usage' and instance_name <> N'_Total')
      OR (instance_name = N'' AND counter_name IN 
           (N'Connection Memory (KB)', N'Granted Workspace Memory (KB)', 
            N'Lock Memory (KB)', N'Optimizer Memory (KB)', N'Stolen Server Memory (KB)', 
            N'Log Pool Memory (KB)', N'Free Memory (KB)')
      ) ORDER BY mb DESC;
    
  • 20 premiers employés

    Vous l'avez déjà fait, mais pour être complet:

    SELECT TOP (21) [type] = COALESCE([type],'Total'), 
      mb = SUM(pages_kb/1024.0)
    FROM sys.dm_os_memory_clerks
    GROUP BY GROUPING SETS((type),())
    ORDER BY mb DESC;
    
  • taille de la pile de threads

    Tout d'abord, assurez-vous qu'il s'agit de zéro, et non d'un certain nombre personnalisé (si ce n'est pas 0, découvrez pourquoi et corrigez-le):

    SELECT value_in_use
      FROM sys.configurations 
      WHERE name = N'max worker threads';
    

    Mais vous pouvez également voir combien de mémoire est occupée par les piles de threads en utilisant:

    SELECT stack_size_in_bytes/1024.0/1024 
      FROM sys.dm_os_sys_info;
    
  • Modules tiers chargés

    SELECT base_address, description, name
      FROM sys.dm_os_loaded_modules 
      WHERE company NOT LIKE N'Microsoft%';
    
    -- you can probably trace down memory usage using the base_address
    
  • DMV liés à la mémoire

    Vous pouvez également être capable de repérer quelque chose hors de l'ordinaire en regardant ces DMV:

    SELECT * FROM sys.dm_os_sys_memory;
    SELECT * FROM sys.dm_os_memory_nodes WHERE memory_node_id <> 64;
    

Cet article a été écrit avant SQL Server 2012, donc certains noms de colonne et calculs peuvent devoir être ajustés, mais peuvent également donner d'autres pistes à essayer:

Quelques bons antécédents dans un autre article sur ce site aussi:

Quelques bonnes informations sur les types de choses qui utilisent de la mémoire en dehors de max server memory (mais pas de bonnes données sur la façon de collecter l'utilisation réelle):

11
Aaron Bertrand

J'ai obtenu ci-dessous la définition de Bob Dorr sur la mémoire maximale du serveur dans les contrôles SQL Server 2012. Vous pouvez également lire Books Online pour plus de détails

La mémoire maximale du serveur contrôle l'allocation de mémoire SQL Server, y compris le pool de mémoire tampon, la mémoire de compilation, tous les caches, les allocations de mémoire qe, la mémoire du gestionnaire de verrouillage et la mémoire CLR (essentiellement tout "commis" tel que trouvé dans dm_os_memory_clerks). Mémoire pour les piles de threads, les tas de mémoire, les fournisseurs de serveurs liés autres que SQL Server ou toute mémoire allouée par un "non SQL Server" DLL n'est pas contrôlée par la mémoire maximale du serveur.

Mémoire allouée à la pile de threads, DLL tierce, fournisseur de serveur lié autre que celui de Microsoft (comme MySQL.PostgreSQL, etc.) ou tout autre DLL chargé dans l'espace d'adressage SQL Server qui n'est pas SQL) Le serveur est alloué en dehors de la mémoire maximale du serveur. L'opération de sauvegarde IIRC dans SQL Server 2012 est également toujours allouée en dehors du pool de mémoire tampon.

Utilisez-vous un serveur lié pour interroger d'autres SGBDR? Tout autre logiciel installé sur la même machine Windows. Pouvez-vous publier sur un emplacement partagé la sortie des requêtes suivantes

select type,
sum(pages_kb)/1024 as [Memory utilized in MB],
sum(awe_allocated_kb)/1024 as [Memory allocated though Windows API]
 from sys.dm_os_memory_clerks
 group by type
 order by [Memory utilized in MB] desc
 Go
-------

 select (virtual_address_space_committed_kb/1024) as virtual_address_space_committed_MB,
 (locked_page_allocations_kb/1024) locked_page_allocations_MB,
 (pages_kb/1024) [memory allocated MB]
  from sys.dm_os_memory_nodes
  Go
-------
SELECT SUM (pages_in_bytes)/1024 as 'KB Used', type 
FROM sys.dm_os_memory_objects
GROUP BY type 
ORDER BY 'KB Used' DESC;
GO
--------
select name,
type,
sum(pages_kb)/1024 as [Mem MB],
sum(entries_count) as [Total Entry count] from sys.dm_os_memory_cache_counters
group by
type, name
order by [Mem MB] desc
Go
-----
select * from sys.dm_os_loaded_modules where company <> 'Microsoft Corporation'
go

Pouvez-vous également télécharger la sortie complète de DBCC MMEMORYSTATUS Sur un emplacement partagé et publier le lien ici. Cela aiderait à comprendre quel composant prend de la mémoire

Edit: Selon la sortie memorystatus dbcc, je peux voir 2 nœuds NUMA et la mémoire utilisée par chaque nœud est d'environ

Node 1 : VM Committed 33554380

Node 2: VM Committed  33554420

Total is approx 64 G. 

Encore une fois, si vous voyez Memory Manager dans memorystatus sortir son

Memory Manager                           KB
---------------------------------------- -----------
VM Reserved                              260726964
VM Committed                             **67108820**

La machine virtuelle validée est en fait une mémoire virtuelle validée par SQL Server et puisque cette mémoire est validée, elle contient physical memory backing it. Cela encore une fois, ce qui me fait penser que SQL Server utilise 65 G comme défini dans la mémoire maximale du serveur

C'est ce qu'est la mémoire maximale du serveur. La mémoire est donc bien répartie entre les deux nœuds. Vous pouvez également ajouter la sortie de la requête ci-dessous pour vérifier. Veuillez ajouter une capture d'écran

SELECT (physical_memory_in_use_kb/1024)/1024 AS [PhysicalMemInUseGB]
FROM sys.dm_os_process_memory;
GO
3
Shanky