Práticas recomendadas para gerir a utilização da memória

Esta página descreve como configurar a utilização de memória para uma instância do Cloud SQL.

Introdução

Quando cria uma instância do Cloud SQL, seleciona uma quantidade de memória para a instância. À medida que a carga de trabalho de uma base de dados PostgreSQL aumenta, a utilização de memória da instância aumenta. As instâncias que consomem muita memória podem criar um gargalo de desempenho que, por vezes, pode levar a problemas de falta de memória.

Quando uma instância do Cloud SQL fica sem memória devido a um aumento da procura, pode causar inatividade da base de dados. Por conseguinte, é importante configurar corretamente a memória da instância e os flags da base de dados relacionados com a memória, bem como monitorizar a utilização da memória para que a instância funcione corretamente.

Os componentes de memória do PostgreSQL estão divididos em duas secções:

  • Memória global: esta é partilhada em todos os processos para executar consultas; por exemplo, shared_buffers e max_connections.
  • Memória local: esta é a memória dedicada atribuída a cada ligação; por exemplo, work_mem, maintenance_work_mem e temp_buffers.

Para outras considerações de configuração, consulte as práticas recomendadas gerais e as diretrizes operacionais.

Utilização de memória e flags

Sempre que houver uma utilização elevada de memória por parte das instâncias do Cloud SQL, podem surgir as seguintes perguntas:

  • Que consulta ou processo está a usar muita memória?
  • As definições de memória são adequadas para a atividade da base de dados?
  • Como é que altero as definições de memória?

Quando uma base de dados PostgreSQL está em funcionamento, a maioria da utilização de memória ocorre em algumas áreas:

  • Buffer partilhado: esta é a memória partilhada que o PostgreSQL atribui para conter dados de tabelas para operações read e write. Para a operação read, todos os dados pedidos do disco são primeiro obtidos para a RAM e, em seguida, são fornecidos ao cliente. Da mesma forma, no PostgreSQL, quando os dados são pedidos (por exemplo, SELECT * from emp), são primeiro obtidos do disco para shared_buffers para colocação em cache e, em seguida, são fornecidos ao cliente. O mesmo acontece com a operação write.

    O buffer partilhado também é a área de memória partilhada para todos os processos e ligações para atividades da base de dados, como o armazenamento em cache de dados, o armazenamento em cache de ligações e as operações da linguagem de manipulação de dados (DML). O máximo que esta área pode atribuir é especificado pelo sinalizador shared_buffers e a predefinição é 33% da memória da instância. Se o valor de shared_buffers for elevado, o tamanho dos dados em cache na memória é elevado.

  • Memória de trabalho da consulta: à medida que uma consulta é executada, o PostgreSQL atribui memória local a cada operação, como a ordenação e a aplicação de hash. O máximo que pode atribuir para cada operação de uma consulta antes de escrever em ficheiros de disco temporários é configurado pela flag work_mem e o valor predefinido é 4 MB. Se o valor de work_mem for elevado, a quantidade de dados que podem ser ordenados na memória é elevada.
  • Memória de trabalho de manutenção: algumas operações de manutenção, como VACUUM, CREATE INDEX, ALTER TABLE e ADD FOREIGN KEY, requerem memória local separada que o PostgreSQL atribui. A quantidade máxima para o processo de back-end que estas operações usam pode ser configurada através da flag maintenance_work_mem e o valor predefinido é de 64 MB. Tenha em atenção que os trabalhadores do autovacuum também usam memória de trabalho de manutenção, e o máximo pode ser substituído pela flag autovacuum_work_mem. Se o valor de maintenance_work_mem for elevado, a velocidade de desempenho da operação VACUUM é elevada.
  • Buffers temporários: quando é usada uma tabela temporária numa sessão da base de dados, o PostgreSQL atribui buffers temporários para reter a tabela temporária local da sessão. A quantidade máxima pode ser especificada através da flag temp_buffers e o valor predefinido é de 8 MB.
  • Ligação à base de dados: quando um cliente se liga à base de dados, o PostgreSQL cria um processo de back-end para servir a sessão do cliente. Além da memória para executar a consulta, o PostgreSQL atribui memória adicional para manter informações, como a cache do catálogo do sistema e os planos de consulta preparados. O número máximo de ligações simultâneas permitidas ao servidor da base de dados pode ser configurado através da flag max_connections. Cada ligação inativa usa aproximadamente 2 MB a 3 MB de memória partilhada. Se o valor de max_connections for elevado, a instância pode estabelecer mais ligações, mas à custa da memória.

Para ver a lista completa de componentes de memória no PostgreSQL, consulte a documentação do PostgreSQL. Para alterar ou modificar as flags indicadas nesta secção, consulte o artigo Configure flags da base de dados.

Monitorize a utilização de memória

Monitorize a memória da sua instância no Cloud Monitoring regularmente e mantenha-a abaixo do limite de memória. Uma boa prática é definir um alerta no Cloud Monitoring para receber um alerta quando a utilização exceder 90% do limite durante 6 horas. Este alerta pode avisar quando a utilização de memória está constantemente perto do limite.

Além disso, monitorize incidentes de falta de memória. Para o fazer, configure uma métrica baseada em registos para a mensagem no Cloud Monitoring para contabilizar os eventos de falta de memória e, em seguida, envie um alerta sempre que ocorrer um evento deste tipo.server process .* was terminated by signal 9: Killed

Se a sua instância funcionar constantemente acima de 90% do limite de memória ou ocorrer um evento de falta de memória, pode aumentar a memória da instância. Em alternativa, pode reduzir a utilização de memória limitando o número de ligações à base de dados ou diminuindo as flags da base de dados, como shared_buffers, work_mem ou max_connections. Diminuir estes indicadores pode limitar o desempenho da sua instância.

Sem memória

Quando não existe memória suficiente para processar a carga de trabalho da base de dados, como último recurso, o sistema operativo Linux subjacente usa o out-of-memory (OOM) killer para terminar um processo e libertar memória. O Cloud SQL está configurado para que o OOM killer tenha como alvo apenas os processos do worker do PostgreSQL. O processo postmaster é preservado nesta situação para que só tenha de terminar todas as ligações existentes à base de dados e executar uma recuperação para proteger a integridade da base de dados. Se isto acontecer, existem momentos de interrupção do serviço e inatividade da base de dados. No registo da base de dados PostgreSQL, aparecem mensagens como as seguintes:

2021-10-24 23:34:22.265 UTC [7]: [663-1] db=,user= LOG: server process (PID 1255039) was terminated by signal 9: Killed
2021-10-24 23:34:22.265 UTC [7]: [664-1] db=,user= DETAIL: Failed process was running: SELECT * FROM tab ORDER BY col
2021-10-24 23:34:22.277 UTC [7]: [665-1] db=,user= LOG: terminating any other active server processes
2021-10-24 23:34:22.278 UTC [1255458]: [1-1] db=postgres,user=postgres WARNING: terminating connection because of crash of another server process
2021-10-24 23:34:22.278 UTC [1255458]: [2-1] db=postgres,user=postgres DETAIL: The postmaster has commanded this server process to roll back the current transaction and exit, because another server process exited abnormally and possibly corrupted shared memory.
2021-10-24 23:34:22.278 UTC [1255458]: [3-1] db=postgres,user=postgres HINT: In a moment you should be able to reconnect to the database and repeat your command.
2021-10-24 23:34:22.278 UTC [1255458]: [4-1] db=postgres,user=postgres CONTEXT: while updating tuple (27,18) in relation "tab"
...
2021-10-24 23:34:22.558 UTC [1255477]: [1-1] db=postgres,user=postgres FATAL: the database system is in recovery mode
...
2021-10-24 23:34:25.579 UTC [7]: [666-1] db=,user= LOG: all server processes terminated; reinitializing
...
2021-10-24 23:34:25.691 UTC [1255482]: [1-1] db=,user= LOG: database system was interrupted; last known up at 2021-10-24 23:31:53 UTC
2021-10-24 23:34:25.776 UTC [1255482]: [2-1] db=,user= LOG: database system was not properly shut down; automatic recovery in progress
2021-10-24 23:34:25.789 UTC [1255482]: [3-1] db=,user= LOG: redo starts at 227/AB359400
2021-10-24 23:34:38.957 UTC [1255482]: [4-1] db=,user= LOG: redo done at 229/4621F508
2021-10-24 23:34:38.959 UTC [1255482]: [5-1] db=,user= LOG: last completed transaction was at log time 2021-10-24 23:34:18.5535+00
2021-10-24 23:34:39.290 UTC [7]: [667-1] db=,user= LOG: database system is ready to accept connections

O que se segue?