Configurando o Killer sem memória no Linux para PostgreSQL


Quando o servidor de banco de dados é encerrado inesperadamente no Linux, você precisa encontrar o motivo. Pode haver várias razões. Por exemplo, SIGSEGV - falha devido a um erro no servidor de back-end. Mas isso é uma raridade. Na maioria das vezes, o espaço em disco ou a memória simplesmente acaba. Se o espaço em disco acabar, uma saída é liberar espaço e reiniciar o banco de dados.


Assassino de falta de memória


Quando o servidor ou processo fica sem memória, o Linux oferece 2 soluções: travar todo o sistema ou encerrar o processo (aplicativo) que consome a memória. É melhor, é claro, concluir o processo e salvar o sistema operacional da finalização anormal. Em poucas palavras, o Killer Sem Memória é o processo que encerra um aplicativo para salvar o kernel de uma falha. Ele sacrifica o aplicativo para manter o sistema operacional em execução. Vamos primeiro discutir como o OOM funciona e como controlá-lo, e depois ver como o OOM Killer decide qual aplicativo finalizar.


Uma das principais tarefas do Linux é alocar memória aos processos quando solicitados. Geralmente, um processo ou aplicativo solicita memória ao sistema operacional, mas eles próprios não a utilizam totalmente. Se o sistema operacional emitir memória para todos que a solicitarem, mas não planeja usá-la, muito em breve a memória terminará e o sistema falhará. Para evitar isso, o sistema operacional reserva memória para o processo, mas na verdade não o emite. A memória é alocada somente quando o processo realmente vai usá-lo. Acontece que o sistema operacional não possui memória livre, mas atribui memória ao processo e, quando o processo precisa, o sistema operacional o aloca, se puder. A desvantagem é que às vezes o sistema operacional reserva memória, mas no momento certo não há memória livre e o sistema trava. OOM desempenha um papel importante nesse cenário e finaliza processos para evitar que o kernel entre em pânico. Quando o processo do PostgreSQL é forçado a terminar, uma mensagem aparece no log:


Out of Memory: Killed process 12345 (postgres). 

Se houver pouca memória no sistema e for impossível out_of_memory la, a função out_of_memory será out_of_memory . Nesse estágio, ela tem apenas uma coisa: concluir um ou mais processos. OOM-killer deve encerrar o processo imediatamente ou posso esperar? Obviamente, quando out_of_memory é chamado, isso ocorre devido à espera de uma operação de E / S ou à troca de página no disco. Portanto, o OOM-killer deve primeiro executar verificações e, com base nelas, decidir que o processo deve ser concluído. Se todas as verificações abaixo derem um resultado positivo, o OOM encerrará o processo.


Seleção de processo


Quando a memória acaba, a função out_of_memory() é out_of_memory() . Possui uma função select_bad_process() , que recebe uma estimativa da função badness() . A distribuição do processo mais "ruim". A função badness() seleciona um processo de acordo com certas regras.


  1. O kernel precisa de alguma memória mínima para si.
  2. Você precisa liberar muita memória.
  3. Não há necessidade de finalizar processos que usam pouca memória.
  4. Você precisa concluir um mínimo de processos.
  5. Algoritmos complexos que aumentam as chances de conclusão dos processos que o próprio usuário deseja concluir.

Depois de concluir todas essas verificações, o OOM examina a nota ( oom_score ). OOM atribui oom_score cada processo e multiplica esse valor pela quantidade de memória. Processos com valores mais altos têm maior probabilidade de se tornarem vítimas do OOM Killer. Os processos associados a um usuário privilegiado têm uma classificação mais baixa e são menos propensos a forçar o encerramento.


 postgres=# SELECT pg_backend_pid(); pg_backend_pid ----------------    3813 (1 row) 

O identificador do processo do Postgres é 3813, portanto, em outro shell, você pode obter uma estimativa usando este oom_score kernel oom_score :


 vagrant@vagrant:~$ sudo cat /proc/3813/oom_score 2 

Se você não deseja que o OOM-Killer conclua o processo, existe outro parâmetro do kernel: oom_score_adj . Adicione um grande valor negativo para reduzir as chances de concluir o processo que você ama.


 sudo echo -100 > /proc/3813/oom_score_adj 

Para definir o valor oom_score_adj , configure OOMScoreAdjust no bloco de serviço:


 [Service] OOMScoreAdjust=-1000 

Ou use oomprotect no rcctl .


 rcctl set <i>servicename</i> oomprotect -1000 

Finalização forçada do processo


Quando um ou mais processos já estão selecionados, o OOM-Killer chama a função oom_kill_task() . Esta função envia um sinal de finalização para o processo. Se não houver memória suficiente, oom_kill() chama esta função para enviar um sinal SIGKILL ao processo. Uma mensagem é gravada no log do kernel.


 Out of Memory: Killed process [pid] [name]. 

Como controlar o OOM-Killer


No Linux, você pode ativar ou desativar o OOM-Killer (embora este último não seja recomendado). Para ativar e desativar, use a opção vm.oom-kill . Para habilitar o OOM-Killer em tempo de execução, execute o comando sysctl .


 sudo -s sysctl -w vm.oom-kill = 1 

Para desativar o OOM-Killer, especifique o valor 0 no mesmo comando:


 sudo -s sysctl -w vm.oom-kill = 0 

O resultado desse comando não será salvo para sempre, mas apenas até a primeira reinicialização. Se você precisar de mais persistência, adicione esta linha ao arquivo /etc/sysctl.conf :


 echo vm.oom-kill = 1 >>/etc/sysctl.conf 

Outra maneira de ativar e desativar é escrever a variável panic_on_oom . O valor sempre pode ser verificado em /proc .


 $ cat /proc/sys/vm/panic_on_oom 0 

Se você definir o valor como 0, quando a memória acabar, o kernel panic não.


 $ echo 0 > /proc/sys/vm/panic_on_oom 

Se você definir o valor como 1, quando a memória acabar, o kernel panic ocorrerá.


 echo 1 > /proc/sys/vm/panic_on_oom 

OOM-Killer não pode apenas ser ligado e desligado. Já dissemos que o Linux pode reservar mais memória para processos do que existe, mas não alocá-la de fato, e esse comportamento é controlado pelo parâmetro do kernel do Linux. A variável vm.overcommit_memory é responsável por isso.


Você pode especificar os seguintes valores para ele:


0: O próprio kernel decide se deve reservar muita memória. Este é o valor padrão na maioria das versões do Linux.
1: o kernel sempre reserva memória extra. Isso é arriscado, porque a memória pode terminar, porque, muito provavelmente, um dia os processos exigirão o que deveria ser.
2: o kernel não reserva mais memória do que o especificado no parâmetro overcommit_ratio .


Neste parâmetro, você especifica a porcentagem de memória para a qual a redundância é permitida. Se não houver espaço, a memória não será alocada, a reserva será negada. Esta é a opção mais segura recomendada para o PostgreSQL. OOM-Killer é afetado por outro elemento - o recurso de troca, que é controlado pela variável cat /proc/sys/vm/swappiness . Esses valores informam ao kernel como lidar com paginação. Quanto maior o valor, menor a probabilidade de o OOM finalizar o processo, mas devido à E / S, isso afeta negativamente o banco de dados. E vice-versa - quanto menor o valor, maior a probabilidade de intervenção do OOM-Killer, mas o desempenho do banco de dados também é maior. O valor padrão é 60, mas se o banco de dados inteiro couber na memória, é melhor definir o valor como 1.


Sumário


Não se assuste com o assassino em OOM-Killer. Nesse caso, o assassino será o salvador do seu sistema. Ele "mata" os piores processos e salva o sistema de terminação anormal. Para evitar ter que usar o OOM-Killer para concluir o PostgreSQL, configure vm.overcommit_memory como 2. Isso não garante que o OOM-Killer não precise intervir, mas reduzirá a probabilidade de um processo forçado do PostgreSQL.

Source: https://habr.com/ru/post/pt464245/


All Articles