Erros de falta de memória de metadados tempdb com otimização de memória (HkTempDB)

Este artigo fornece resoluções para solucionar problemas de falta de memória relacionados ao recurso de metadados com otimização tempdb de memória.

Sintomas

Depois de habilitar o recurso de metadados com otimização tempdb de memória (HkTempDB), você poderá ver o erro 701 indicando exceções de memória insuficiente para tempdb alocações e falhas do Serviço SQL Server. Além disso, você pode ver que o coletor MEMORYCLERK_XTP de memória para OLTP in-memory (Hekaton) está crescendo gradual ou rapidamente e não diminui. À medida que a memória XTP cresce sem um limite superior, você vê a seguinte mensagem de erro no SQL Server:

Não permitir alocações de página para o banco de dados 'tempdb' devido à memória insuficiente no pool de recursos 'default'. Consulte “http://go.microsoft.com/fwlink/?LinkId=510837” para obter mais informações.

Ao executar uma consulta no dm_os_memory_clerks DMV, você pode ver que a memória de páginas alocada é alta para o funcionário MEMORYCLERK_XTPde memória. Por exemplo:

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

Resultado:

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

Diagnosticar o problema

Para coletar dados para diagnosticar o problema, siga estas etapas:

  1. Colete um rastreamento leve ou um evento estendido (XEvent) para entender tempdb a carga de trabalho e descubra se a carga de trabalho tem transações explícitas de longa execução com instruções DDL em tabelas temporárias.

  2. Colete a saída dos seguintes DMVs para analisar mais.

    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
    

Causa e resolução

Usando as DMVs para verificar a causa, você pode ver diferentes cenários do problema. Esses cenários podem ser divididos nas duas categorias a seguir. Para resolver o problema, você pode usar a resolução correspondente para cada cenário. Para obter mais informações sobre como aliviar o problema, consulte Etapas de mitigação para manter a memória de metadados tempdb com otimização de memória sob controle.

Aumento gradual no consumo de memória XTP

  • Cenário 1

    A DMV tempdb.sys.dm_xtp_system_memory_consumers ou tempdb.sys.dm_db_xtp_memory_consumers mostra uma grande diferença entre bytes alocados e bytes usados.

    Resolução: para resolver o problema, você pode executar os seguintes comandos no SQL Server 2019 CU13, SQL Server 2022 CU1 ou em uma versão posterior que tenha um novo procedimento sys.sp_xtp_force_gc para liberar bytes alocados, mas não utilizados.

    Observação

    A partir do SQL Server 2022 CU1, você precisa executar o procedimento armazenado apenas uma vez.

    /* 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
    
  • Cenário 2

    A DMV tempdb.sys.dm_xtp_system_memory_consumers mostra valores altos para bytes alocados e usados para tipos VARHEAP de consumidor de memória e LOOKASIDE.

    Resolução: verifique se há transações explícitas de longa execução envolvendo instruções DDL em tabelas temporárias e resolva do lado do aplicativo, mantendo as transações curtas.

    Observação

    Para reproduzir esse problema em um ambiente de teste, você pode criar uma transação explícita usando instruções DDL (Data Definition Language) em tabelas temporárias e deixá-la aberta por um longo tempo quando outra atividade ocorrer.

  • Cenário 3

    A DMV tempdb.sys.dm_db_xtp_memory_consumers mostra valores altos para bytes alocados e usados em um alocador de objeto grande (LOB) ou heap de tabela em que Object_ID, XTP_Object_ID, e Index_ID são NULL.

    Resolução: aplique o SQL Server 2019 CU16 para o problema 14535149.

  • Cenário 4

    O crescente consumo de memória de banco de dados XTP "VARHEAP\Storage internal heap" leva ao erro de falta de memória 41805.

    Resolução: o problema já 14087445 identificado e resolvido no SQL Server 17 CU25 e versões posteriores está sendo examinado para ser portado para o SQL Server 2019.

Pico repentino ou aumento rápido no consumo de memória XTP

  • Cenário 5

    A DMV tempdb.sys.dm_db_xtp_memory_consumers mostra valores altos para bytes alocados ou usados em um heap de tabela em que Object_ID não NULLé . A causa mais comum desse problema é uma transação de longa execução e explicitamente aberta com instruções DDL em tabelas temporárias. Por exemplo:

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

    Uma transação explicitamente aberta com instruções DDL em tabelas temporárias não permitirá que o heap de tabela e o heap lookaside sejam liberados para transações subsequentes usando tempdb metadados.

    Resolução: verifique se há transações explícitas de longa execução envolvendo instruções DDL em tabelas temporárias e resolva do lado do aplicativo, mantendo as transações curtas.

Etapas de mitigação para manter a memória de metadados tempdb com otimização de memória sob controle

  1. Para evitar ou resolver transações de longa duração que usam instruções DDL em tabelas temporárias, a orientação geral é manter as transações curtas.

  2. Aumente a memória máxima do servidor para permitir memória suficiente para operar na presença de cargas de trabalho pesadas de tempdb.

  3. Execute sys.sp_xtp_force_gc periodicamente.

  4. Para proteger o servidor de possíveis condições de falta de memória, você pode associar tempdb a um pool de recursos do Administrador de Recursos. Por exemplo, crie um pool de recursos usando MAX_MEMORY_PERCENT = 30o . Em seguida, use o seguinte comando ALTER SERVER CONFIGURATION para associar o pool de recursos a metadados tempdb com otimização de memória.

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

    Essa alteração requer uma reinicialização para entrar em vigor, mesmo que os metadados com otimização tempdb de memória já estejam habilitados. Para saber mais, veja:

    Aviso

    Depois de associar o HktempDB a um pool, o pool pode atingir sua configuração máxima e todas as consultas usadas tempdb podem falhar com erros de memória insuficiente. Por exemplo:

    Não permitir alocações de página para o banco de dados 'tempdb' devido à memória insuficiente no pool de recursos 'HkTempDB'. Consulte “http://go.microsoft.com/fwlink/?LinkId=510837” para obter mais informações. O XTP falhou na alocação de páginas devido à pressão de memória: FAIL_PAGE_ALLOCATION 8

    Em determinadas circunstâncias, o serviço SQL Server pode ser interrompido se ocorrer um erro de memória insuficiente. Para reduzir a chance de isso acontecer, defina o pool de MAX_MEMORY_PERCENT memória como um valor alto.

  5. O recurso de metadados com otimização tempdb de memória não dá suporte a todas as cargas de trabalho. Por exemplo, o uso de transações explícitas com instruções DDL em tabelas temporárias que são executadas por um longo tempo levará aos cenários descritos. Se você tiver essas transações em sua carga de trabalho e não puder controlar sua duração, talvez esse recurso não seja apropriado para seu ambiente. Você deve testar extensivamente antes de usar HkTempDBo .

Mais informações

Essas seções fornecem mais detalhes sobre alguns dos componentes de memória envolvidos em metadados com otimização tempdb de memória.

Alocador de memória Lookaside

Lookaside no OLTP In-Memory é um alocador de memória local de thread para ajudar a obter processamento rápido de transações. Cada objeto thread contém uma coleção de alocadores de memória lookside. Cada lookaside associado a cada thread tem um limite superior predefinido de quanta memória ele pode alocar. Quando o limite é atingido, o thread aloca memória de um pool de memória compartilhada de transbordamento (VARHEAP). A DMV sys.dm_xtp_system_memory_consumers agrega dados para cada tipo lookaside (memory_consumer_type_desc = 'LOOKASIDE') e o pool de memória compartilhada (memory_consumer_type_desc = 'VARHEAP' e memory_consumer_desc = 'Lookaside heap').

Consumidores no nível do sistema: tempdb.sys.dm_xtp_system_memory_consumers

Cerca de 25 tipos de consumidores de memória lookaside são o limite superior. Quando os threads precisam de mais memória desses lookasides, a memória transborda e fica satisfeita com o heap lookside. Valores altos para bytes usados podem ser um indicador de carga de trabalho pesada tempdb constante e/ou transação aberta de longa duração que usa objetos temporários.

-- 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

Consumidores no nível do banco de dados: tempdb.sys.dm_db_xtp_memory_consumers

  • O alocador de LOB é usado para tabelas do sistema Dados LOB/Off-row.

  • O heap da tabela é usado para linhas de tabelas do sistema.

Valores altos para bytes usados podem ser o indicador de carga de trabalho pesada tempdb constante e/ou transação aberta de longa execução que usa objetos temporários.