Otimizar o consumo elevado de memória nas instâncias

É um problema comum que as instâncias consumam muita memória ou tenham problemas de falta de memória (OOM). Uma instância de banco de dados em execução com alta utilização de memória geralmente causa problemas de desempenho, interrupções ou até mesmo inatividade no banco de dados.

Alguns blocos de memória do MySQL são usados globalmente. Isso significa que todas as cargas de trabalho de consulta compartilham locais de memória, são ocupadas o tempo todo e liberadas apenas quando o processo do MySQL é interrompido. Alguns blocos de memória são baseados em sessões, o que significa que, assim que a sessão é encerrada, a memória usada por ela também é liberada para o sistema.

O Cloud SQL recomenda que você identifique a consulta ou o processo que está usando muita memória para liberar a memória. O consumo de memória do MySQL é dividido em três partes principais:

  • Linhas de execução e consumo de memória de processo
  • Consumo de memória do buffer
  • Consumo de memória em cache

Linhas de execução e consumo de memória de processo

Cada sessão do usuário consome memória, dependendo das consultas em execução, dos buffers ou do cache usados por ela e é controlada pelos parâmetros da sessão do MySQL. Os principais parâmetros incluem:

  • thread_stack
  • net_buffer_length
  • read_buffer_size
  • read_rnd_buffer_size
  • sort_buffer_size
  • join_buffer_size
  • max_heap_table_size
  • tmp_table_size

Se houver N números de consultas em execução em um momento específico, cada consulta consumirá memória de acordo com esses parâmetros durante a sessão.

Consumo de memória do buffer

Essa parte da memória é comum para todas as consultas e é controlada por parâmetros como Innodb_buffer_pool_size, Innodb_log_buffer_size e key_buffer_size.

Consumo de memória em cache

A memória do cache inclui um cache de consulta, que é usado para salvar as consultas e os resultados delas para a recuperação mais rápida dos mesmos dados das consultas subsequentes. Ele também inclui o cache binlog para manter as mudanças feitas no registro binário enquanto a transação está em execução e é controlado por binlog_cache_size.

Outro consumo de memória

A memória também é usada por operações de ordenação e mesclagem. Se as consultas usarem operações de mesclagem ou ordenação, elas usarão a memória com base em join_buffer_size e sort_buffer_size.

Além disso, se você ativar o esquema de desempenho, ele consumirá memória. Para verificar o uso da memória pelo esquema de desempenho, use a seguinte consulta:

SELECT *
FROM
  performance_schema.memory_summary_global_by_event_name
WHERE EVENT_NAME LIKE 'memory/performance_schema/%';

Existem muitos instrumentos disponíveis no MySQL que podem ser configurados para monitorar o uso de memória no esquema de desempenho. Para saber mais, consulte a documentação do MySQL.

O parâmetro relacionado ao MyISAM para a inserção de dados em massa é bulk_insert_buffer_size.

Para saber mais sobre como o MySQL usa a memória, consulte a documentação do MySQL.

recomendações

Usar o Metrics Explorer para identificar o uso da memória

É possível analisar o uso de memória de uma instância com a métrica database/memory/components.usage no Metrics Explorer.

Se você tiver menos de 5% de memória em database/memory/components.cache e em database/memory/components.free combinados, o risco de um evento OOM será alto. Para monitorar o uso da memória e evitar eventos OOM, recomendamos configurar uma política de alertas com uma condição de limite de métrica de 95% ou mais em database/memory/components.usage.

A seguinte tabela mostra a relação entre a memória da instância e o limite de alertas recomendado:

Memória da instância Limite de alertas recomendado
Até 100 GB 95%
100 GB a 200 GB 96%
200 GB a 300 GB 97%
Mais de 300 GB 98%

Calcular o consumo de memória

Calcule o uso máximo de memória pelo seu banco de dados MySQL para selecionar o tipo de instância apropriado. Use a seguinte fórmula:

Uso máximo de memória do MySQL = innodb_buffer_pool_size + innodb_additional_mem_pool_size + innodb_log_buffer_size + tmp_table_size + key_buffer_size + ((read_buffer_size + read_rnd_buffer_size + sort_buffer_size + join_buffer_size) x max_connections)

Veja os parâmetros usados na fórmula:

  • innodb_buffer_pool_size: o tamanho em bytes do pool de buffers, a área de memória em que o InnoDB armazena em cache os dados de tabela e índice.
  • innodb_additional_mem_pool_size: o tamanho em bytes de um pool de memória que o InnoDB usa para armazenar informações de dicionários de dados e outras estruturas internas de dados.
  • innodb_log_buffer_size: o tamanho em bytes do buffer que o InnoDB usa para gravar nos arquivos de registros no disco.
  • tmp_table_size: o tamanho máximo das tabelas temporárias na memória criadas pelo mecanismo de armazenamento MEMORY e pelo TempTable a partir do MySQL 8.0.28.
  • Key_buffer_size: o tamanho do buffer usado para blocos de índice. Blocos de índice para tabelas MyISAM são armazenados em buffer e compartilhados por todas as linhas de execução.
  • Read_buffer_size: cada linha de execução que faz uma verificação sequencial de uma tabela MyISAM aloca um buffer desse tamanho (em bytes) para cada tabela verificada.
  • Read_rnd_buffer_size: essa variável é usada para leituras de tabelas MyISAM, para qualquer mecanismo de armazenamento e para otimização de leitura multiintervalo.
  • Sort_buffer_size: cada sessão que precisa realizar uma classificação aloca um buffer desse tamanho. O sort_buffer_size não é específico para nenhum mecanismo de armazenamento e se aplica de maneira geral para otimização.
  • Join_buffer_size: o tamanho mínimo do buffer usado para verificações de índice simples, verificações de índice de intervalo e mesclagens que não usam índices e, portanto, executam verificações de tabela completas.
  • Max_connections: o número máximo permitido de conexões simultâneas do cliente.

Resolver problemas de alto consumo de memória

  • Execute SHOW PROCESSLIST para ver as consultas em andamento que consomem memória no momento. Ele exibe todas as linhas de execução conectadas e as instruções SQL em execução no momento e tenta otimizá-las. Preste atenção nas colunas de estado e duração.

    mysql> SHOW [FULL] PROCESSLIST;
    
    
  • Verifique SHOW ENGINE INNODB STATUS na seção BUFFER POOL AND MEMORY para ver o uso atual de pool de buffers e memória, que pode ajudar a definir o tamanho do pool de buffers.

    mysql> SHOW ENGINE INNODB STATUS \G
    ----------------------
    BUFFER POOL AND MEMORY
    ----------------------
    Total memory allocated 398063986; in additional pool allocated 0
    Dictionary memory allocated 12056
    Buffer pool size 89129
    Free buffers 45671
    Database pages 1367
    Old database pages 0
    Modified db pages 0
    
  • Use o comando SHOW variables do MySQL para verificar os valores do contador, que fornecem informações como número de tabelas temporárias, número de linhas de execução, número de caches de tabela, páginas sujas, tabelas abertas e uso do pool de buffers.

    mysql> SHOW variables like 'VARIABLE_NAME'
    

Aplicar alterações

Depois de analisar o uso da memória por diferentes componentes, defina o flag apropriado no banco de dados MySQL. Para alterar o flag na instância do Cloud SQL para MySQL, use o console do Google Cloud ou a CLI gcloud. Para alterar o valor do flag usando o console do Google Cloud, edite a seção Flags, selecione o flag e digite o novo valor.

Por fim, se o uso de memória ainda estiver alto e você achar que as consultas e os valores dos flags estão otimizados, considere aumentar o tamanho da instância para evitar OOM.