Erreurs de mémoire insuffisante dans les métadonnées tempdb optimisées (HkTempDB)

Cet article fournit des solutions pour résoudre les problèmes de mémoire insuffisante liés à la fonctionnalité de métadonnées optimisées en tempdb mémoire.

Symptômes

Après avoir activé la fonctionnalité de métadonnées optimisées tempdb en mémoire (HkTempDB), vous pouvez voir l’erreur 701 indiquant des exceptions de mémoire insuffisante pour tempdb les allocations et les blocages du service SQL Server. En outre, vous pouvez voir que le commis MEMORYCLERK_XTP de mémoire pour In-Memory OLTP (Hekaton) augmente progressivement ou rapidement et ne se réduit pas. À mesure que la mémoire XTP augmente sans limite supérieure, le message d’erreur suivant s’affiche dans SQL Server :

Interdiction des allocations de pages pour la base de données « tempdb » en raison d’une mémoire insuffisante dans le pool de ressources « default ». Pour plus d’informations, consultez «http://go.microsoft.com/fwlink/?LinkId=510837 ».

Lorsque vous exécutez une requête sur la DMVdm_os_memory_clerks, vous pouvez voir que la mémoire allouée aux pages est élevée pour le commis de MEMORYCLERK_XTPmémoire . Par exemple :

SELECT type, memory_node_id, pages_kb 
FROM sys.dm_os_memory_clerks
WHERE type = 'MEMORYCLERK_XTP'

Résultat:

type                    memory_node_id                     pages_kb
------------------------------------------------------------ -------------- --------------------
MEMORYCLERK_XTP         0                                  60104496
MEMORYCLERK_XTP         64                                 0

Diagnostiquer le problème

Pour collecter des données afin de diagnostiquer le problème, procédez comme suit :

  1. Collectez une trace légère ou un événement étendu (XEvent) pour comprendre tempdb la charge de travail et déterminer si la charge de travail a des transactions explicites de longue durée avec des instructions DDL sur des tables temporaires.

  2. Collectez la sortie des vues de gestion dynamique suivantes pour les analyser plus en détail.

    SELECT * FROM sys.dm_os_memory_clerks
    SELECT * FROM sys.dm_exec_requests
    SELECT * FROM sys.dm_exec_sessions
    
    -- from tempdb
    SELECT * FROM tempdb.sys.dm_xtp_system_memory_consumers 
    SELECT * FROM tempdb.sys.dm_db_xtp_memory_consumers
    
    SELECT * FROM tempdb.sys.dm_xtp_transaction_stats
    SELECT * FROM tempdb.sys.dm_xtp_gc_queue_stats
    SELECT * FROM tempdb.sys.dm_db_xtp_object_stats
    
    SELECT * FROM tempdb.sys.dm_db_xtp_transactions
    SELECT * FROM tempdb.sys.dm_tran_session_transactions
    SELECT * FROM tempdb.sys.dm_tran_database_transactions
    SELECT * FROM tempdb.sys.dm_tran_active_transactions
    

Cause et résolution

En utilisant les vues de gestion dynamique pour vérifier la cause, vous pouvez voir différents scénarios du problème. Ces scénarios peuvent être divisés en deux catégories. Pour résoudre le problème, vous pouvez utiliser la résolution correspondante pour chaque scénario. Pour plus d’informations sur la façon d’atténuer le problème, consultez Étapes d’atténuation pour conserver la mémoire des métadonnées tempdb optimisées en mémoire dans case activée.

Augmentation progressive de la consommation de mémoire XTP

  • Scénario 1

    La DMV tempdb.sys.dm_xtp_system_memory_consumers ou tempdb.sys.dm_db_xtp_memory_consumers montre une grande différence entre les octets alloués et les octets utilisés.

    Résolution : pour résoudre le problème, vous pouvez exécuter les commandes suivantes dans SQL Server 2019 CU13, SQL Server 2022 CU1 ou une version ultérieure qui a une nouvelle procédure sys.sp_xtp_force_gc pour libérer les octets alloués mais inutilisés.

    Remarque

    À compter de SQL Server 2022 CU1, vous devez exécuter la procédure stockée une seule fois.

    /* Yes, 2 times for both*/
    EXEC sys.sp_xtp_force_gc 'tempdb'
    GO
    EXEC sys.sp_xtp_force_gc 'tempdb'
    GO
    EXEC sys.sp_xtp_force_gc
    GO
    EXEC sys.sp_xtp_force_gc
    
  • Scénario 2

    La DMV tempdb.sys.dm_xtp_system_memory_consumers affiche des valeurs élevées pour les octets alloués et utilisés pour les types VARHEAP de consommateurs mémoire et LOOKASIDE.

    Résolution : recherchez les transactions explicites de longue durée impliquant des instructions DDL sur des tables temporaires et résolvez-les côté application en conservant des transactions courtes.

    Remarque

    Pour reproduire ce problème dans un environnement de test, vous pouvez créer une transaction explicite à l’aide d’instructions DDL (Data Definition Language) sur des tables temporaires et la laisser ouverte pendant une longue période lorsque d’autres activités ont lieu.

  • Scénario 3

    La vue dynamique tempdb.sys.dm_db_xtp_memory_consumers dynamique affiche des valeurs élevées pour les octets alloués et utilisés dans un allocateur d’objet volumineux (LOB) ou un tas de table où Object_ID, XTP_Object_IDet Index_ID sont NULL.

    Résolution : appliquez SQL Server 2019 CU16 pour le problème 14535149.

  • Scénario 4

    La croissance continue du consommateur de mémoire de base de données XTP « VARHEAP\Storage internal heap » entraîne une erreur de mémoire insuffisante 41805.

    Résolution : le problème 14087445 déjà identifié et résolu dans SQL Server 17 CU25 et versions ultérieures est en cours d’examen pour être transféré vers SQL Server 2019.

Pic soudain ou augmentation rapide de la consommation de mémoire XTP

  • Scénario 5

    La vue dynamique tempdb.sys.dm_db_xtp_memory_consumers dynamique affiche des valeurs élevées pour les octets alloués ou utilisés dans un tas de table où Object_ID n’est pas NULL. La cause la plus courante de ce problème est une transaction ouverte de longue durée avec des instructions DDL sur des tables temporaires. Par exemple :

    BEGIN TRAN
        CREATE TABLE #T(sn int)
        …
        …
    COMMIT
    

    Une transaction ouverte explicitement avec des instructions DDL sur des tables temporaires ne permet pas de libérer le tas de table et le tas de recherche pour les transactions suivantes à l’aide tempdb de métadonnées.

    Résolution : recherchez les transactions explicites de longue durée impliquant des instructions DDL sur des tables temporaires et résolvez-les côté application en conservant des transactions courtes.

Étapes d’atténuation pour conserver la mémoire des métadonnées tempdb optimisées en mémoire dans case activée

  1. Pour éviter ou résoudre les transactions de longue durée qui utilisent des instructions DDL sur des tables temporaires, l’aide générale consiste à conserver des transactions courtes.

  2. Augmentez la mémoire maximale du serveur pour permettre à suffisamment de mémoire pour fonctionner en présence de charges de travail lourdes de tempdb.

  3. Exécutez sys.sp_xtp_force_gc régulièrement.

  4. Pour protéger le serveur contre les éventuels problèmes de mémoire insuffisante, vous pouvez lier tempdb à un pool de ressources Resource Governor. Par exemple, créez un pool de ressources à l’aide MAX_MEMORY_PERCENT = 30de . Ensuite, utilisez la commande ALTER SERVER CONFIGURATION suivante pour lier le pool de ressources aux métadonnées tempdb optimisées en mémoire.

    ALTER SERVER CONFIGURATION SET MEMORY_OPTIMIZED TEMPDB_METADATA = ON (RESOURCE_POOL = '<PoolName>');
    

    Cette modification nécessite un redémarrage pour prendre effet, même si les métadonnées mémoire optimisées sont déjà activées tempdb . Pour plus d’informations, consultez l’article suivant :

    Avertissement

    Après avoir lié HktempDB à un pool, le pool peut atteindre son paramètre maximal et toutes les requêtes qui utilisent tempdb peuvent échouer avec des erreurs de mémoire insuffisante. Par exemple :

    Interdiction des allocations de pages pour la base de données « tempdb » en raison d’une mémoire insuffisante dans le pool de ressources « HkTempDB ». Pour plus d’informations, consultez «http://go.microsoft.com/fwlink/?LinkId=510837 ». Échec de l’allocation de pages XTP en raison d’une sollicitation de la mémoire : FAIL_PAGE_ALLOCATION 8

    Dans certaines circonstances, le service SQL Server peut s’arrêter si une erreur de mémoire insuffisante se produit. Pour réduire le risque que cela se produise, définissez les valeurs du pool de MAX_MEMORY_PERCENT mémoire sur une valeur élevée.

  5. La fonctionnalité de métadonnées optimisées en tempdb mémoire ne prend pas en charge toutes les charges de travail. Par exemple, l’utilisation de transactions explicites avec des instructions DDL sur des tables temporaires qui s’exécutent pendant une longue période entraîne les scénarios décrits. Si vous avez de telles transactions dans votre charge de travail et que vous ne pouvez pas contrôler leur durée, cette fonctionnalité n’est peut-être pas appropriée pour votre environnement. Vous devez effectuer des tests approfondis avant d’utiliser HkTempDB.

Plus d’informations

Ces sections fournissent plus d’informations sur certains composants de mémoire impliqués dans les métadonnées mémoire optimisées tempdb .

Allocateur de mémoire lookaside

Lookaside dans In-Memory OLTP est un allocateur de mémoire locale de thread qui permet d’obtenir un traitement transactionnel rapide. Chaque objet thread contient une collection d’allocateurs de mémoire de lookaside. Chaque lookaside associé à chaque thread a une limite supérieure prédéfinie sur la quantité de mémoire qu’il peut allouer. Lorsque la limite est atteinte, le thread alloue de la mémoire à partir d’un pool de mémoire partagée de débordement (VARHEAP). La DMV sys.dm_xtp_system_memory_consumers agrège les données pour chaque type de lookaside (memory_consumer_type_desc = 'LOOKASIDE') et le pool de mémoire partagée (memory_consumer_type_desc = 'VARHEAP' et memory_consumer_desc = 'Lookaside heap').

Consommateurs au niveau du système : tempdb.sys.dm_xtp_system_memory_consumers

Environ 25 types de consommateurs de mémoire lookaside constituent la limite supérieure. Lorsque les threads ont besoin de plus de mémoire à partir de ces lookasides, la mémoire se répand sur et est satisfaite du tas de lookaside. Les valeurs élevées des octets utilisés peuvent être un indicateur d’une charge de travail élevée constante tempdb et/ou d’une transaction ouverte de longue durée qui utilise des objets temporaires.

-- system memory consumers @ instance  
SELECT memory_consumer_type_desc, memory_consumer_desc, allocated_bytes, used_bytes
FROM sys.dm_xtp_system_memory_consumers 
memory_consumer_type_desc     memory_consumer_desc                   allocated_bytes      used_bytes
------------------------- ------------------------------------------ -------------------- --------------------
VARHEAP                       Lookaside heap                             0                    0
PGPOOL                        256K page pool                             0                    0
PGPOOL                        4K page pool                               0                    0
VARHEAP                       System heap                                458752               448000
LOOKASIDE                     Transaction list element                   0                    0
LOOKASIDE                     Delta tracker cursor                       0                    0
LOOKASIDE                     Transaction delta tracker                  0                    0
LOOKASIDE                     Creation Statement Id Map Entry            0                    0
LOOKASIDE                     Creation Statement Id Map                  0                    0
LOOKASIDE                     Log IO proxy                               0                    0
LOOKASIDE                     Log IO completion                          0                    0
LOOKASIDE                     Sequence object insert row                 0                    0
LOOKASIDE                     Sequence object map entry                  0                    0
LOOKASIDE                     Sequence object values map                 0                    0
LOOKASIDE                     Redo transaction map entry                 0                    0
LOOKASIDE                     Transaction recent rows                    0                    0
LOOKASIDE                     Heap cursor                                0                    0
LOOKASIDE                     Range cursor                               0                    0
LOOKASIDE                     Hash cursor                                0                    0
LOOKASIDE                     Transaction dependent ring buffer          0                    0
LOOKASIDE                     Transaction save-point set entry           0                    0
LOOKASIDE                     Transaction FK validation sets             0                    0
LOOKASIDE                     Transaction partially-inserted rows set    0                    0
LOOKASIDE                     Transaction constraint set                 0                    0
LOOKASIDE                     Transaction save-point set                 0                    0
LOOKASIDE                     Transaction write set                      0                    0
LOOKASIDE                     Transaction scan set                       0                    0
LOOKASIDE                     Transaction read set                       0                    0
LOOKASIDE                     Transaction                                0                    0

Consommateurs au niveau de la base de données : tempdb.sys.dm_db_xtp_memory_consumers

  • L’allocateur LOB est utilisé pour les données métier/hors ligne des tables système.

  • Le tas de table est utilisé pour les lignes des tables système.

Les valeurs élevées des octets utilisés peuvent être l’indicateur d’une charge de travail élevée tempdb constante et/ou d’une transaction ouverte de longue durée qui utilise des objets temporaires.