web-dev-qa-db-fra.com

Que se passe-t-il lorsqu'il n'y a plus de mémoire physique disponible pour SQL Server?

En cherchant sur Google, j'ai trouvé des informations contradictoires.

Certains sites indiquent que lorsqu'il n'y a plus de mémoire physique pour les données, alors SQL Server déplace les données déjà existantes dans TEMPDB (voir: SQL Server: Démystifier TempDb et recommandations ).

Mais d'autres sites indiquent que, lorsqu'il n'y a pas assez de mémoire physique, le système d'exploitation peut utiliser le FICHIER DE PAGE et y déplacer des données de la mémoire physique (voir Fichier de page pour SQL Server ).

Je me demande où SQL Server écrit des données lorsqu'il manque de mémoire physique? Pour tempdb ou vers le fichier OS Page? Ou peut-être les deux?

16
RaufDBA

lorsqu'il n'y a plus de mémoire physique pour les données, SQL Server déplace les données déjà existantes dans TEMPDB

L'article auquel vous avez lié est au mieux trompeur et incorrect à certains endroits. Je pense que l'auteur tentait de simplifier à l'excès certaines choses compliquées et, ce faisant, est allé un peu trop loin.

SQL Server ne déplace pas les données de la mémoire (le pool de tampons) dans tempdb de cette façon. Il utilise une stratégie de mise en cache "la moins récemment utilisée" (en général), donc s'il y a une pression mémoire et que de nouvelles données doivent être extraites en mémoire, SQL Server supprimera les données LRU du pool de mémoire tampon pour accueillir les nouvelles données. Ce comportement est souvent surveillé par un compteur perfmon appelé "Page Life Espérance" (PLE) :

La définition de PLE est le temps attendu, en secondes, qu'une page de fichier de données lue dans le pool de mémoire tampon (le cache en mémoire des pages de fichiers de données) restera en mémoire avant d'être poussée hors de la mémoire pour faire de la place pour des données différentes page de fichier. Une autre façon de penser au PLE est une mesure instantanée de la pression sur le pool de mémoire tampon pour libérer de l'espace pour les pages lues sur le disque. Pour ces deux définitions, un nombre plus élevé est préférable.

Pendant l'exécution de la requête, SQL Server peut utiliser tempdb pour certaines opérations. Cela se fait généralement si les estimations sont mauvaises, mais la faible mémoire disponible peut influencer ce comportement.

Certaines des opérations qui peuvent "se répandre" dans tempdb de cette manière sont le hachage de lignes (pour les jointures ou les agrégats, etc.), le tri des lignes en mémoire et la mise en mémoire tampon des lignes lors de l'exécution de requêtes parallèles.

Les requêtes des utilisateurs peuvent également utiliser explicitement tempdb (avec des tables temporaires globales ou locales) et implicitement utiliser tempdb (avec un instantané ou lire des niveaux d'isolement de snapshot validés).

Aucune de ces situations ne semble vraiment correspondre à la déclaration que vous avez citée.

lorsqu'il n'y a pas assez de mémoire physique, le système d'exploitation peut utiliser le FICHIER DE PAGE et y déplacer des données de la mémoire physique

Cela peut certainement se produire et échappe en grande partie au contrôle de SQL Server. Il y a un bouton que vous pouvez tourner pour essayer d'empêcher certains types de pagination au niveau du système d'exploitation, à savoir activer "Lock Pages in Memory" (LPIM) :

Cette stratégie Windows détermine quels comptes peuvent utiliser un processus pour conserver les données dans la mémoire physique, empêchant le système de paginer les données vers la mémoire virtuelle sur le disque.

Alors, que pouvons-nous empêcher d'être paginé sur le disque?

Avant SQL Server 2012, les pages allouées via un composant appelé "Single Page Allocator" étaient verrouillées en mémoire (ne pouvaient pas être paginées). Cela comprenait le pool de mémoire tampon (pages de base de données), le cache de procédure et d'autres zones de mémoire.

Voir Fun with Locked Pages, AWE, Task Manager, and the Working Set… pour plus de détails, en particulier la section "4. Maintenant, je sais que SQL Server sur x64 peut utiliser" Pages verrouillées ", ce qui est exactement fermé à clé?" Des lectures connexes supplémentaires peuvent être trouvées ici: Great SQL Server Debates: Lock Pages in Memory

Dans SQL Server 2012 et versions ultérieures, il n'y a pas d'allocateur de page unique (les allocateurs de page unique et multipage ont été fusionnés, par n examen approfondi de la mémoire - SQL Server 2012/2014 ). Les détails de ce qui, exactement, peut et ne peut pas être paginé ne sont pas documentés en détail partout où j'ai vu. Vous pouvez utiliser une requête comme celle-ci pour voir ce que est verrouillé:

select osn.node_id, osn.memory_node_id, osn.node_state_desc, omn.locked_page_allocations_kb
from sys.dm_os_memory_nodes omn
inner join sys.dm_os_nodes osn on (omn.memory_node_id = osn.memory_node_id)
where osn.node_state_desc <> 'ONLINE DAC'

Selon le même article du support MS, vous pouvez également utiliser DBCC MEMORYSTATUS pour voir la quantité de mémoire "verrouillée".

En guise de remarque, vous pouvez voir la preuve que l'ensemble de travail de SQL Server est paginé par le système d'exploitation dans le journal des erreurs. Il y aura des messages qui ressemblent à ceci:

2019-09-02 10: 19: 27.29 spid11s Une partie importante de la mémoire de processus du serveur SQL a été paginée. Cela peut entraîner une dégradation des performances. Durée: 329 secondes. Ensemble de travail (Ko): 68780, engagé (Ko): 244052, utilisation de la mémoire: 28%.

28
Josh Darnell

Les versions modernes de SQL Server ont très peu de chances de raccrocher. SQL Server charge .NET Framework dans son espace d'adressage et l'utilise en fonctionnement normal. Si la mémoire physique et le fichier d'échange s'épuisent tous les deux, Windows essaiera d'agrandir le fichier d'échange; cependant, même s'il peut agrandir le fichier d'échange, ce n'est pas une opération instantanée et les allocations de mémoire échouent pendant que le fichier d'échange se développe. Il y a un bogue dans le gestionnaire d'E/S asynchrone .NET où il alloue de la mémoire en réponse à une notification APC. Si l'appel à new échoue, il lancera OutOfMemoryException. Cette exception est interceptée dans le code natif à l'intérieur du planificateur de tâches; cependant, les E/S asynchrones semblent ne jamais se terminer. Le thread du finaliseur pour FileStream bloquera l'attente de la fin des E/S afin de pouvoir désépingler le tampon, suspendant ainsi le thread du finaliseur pour toujours. Cela provoque .NET Framework à utiliser progressivement de plus en plus de mémoire jusqu'à ce que plus de mémoire ne puisse être allouée, auquel cas le serveur SQL ne répondra plus car winsock ne peut plus allouer de tampons, de sorte que même la connexion d'accès administrateur est inutile.

J'ai en fait atteint un blocage total du planificateur de tâches dans une application .NET en raison d'un manque de mémoire. Heureusement, le processus est finalement mort en raison du lancement de OutOfMemoryException sur un thread qui ne l'a pas intercepté après plusieurs échecs afin que nous puissions comprendre ce qui bloquait réellement le serveur.

Une fois que je savais ce que je cherchais, trouver le bogue dans l'analyse statique était facile.

0
Joshua