
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.
- O kernel precisa de alguma memória mínima para si.
- Você precisa liberar muita memória.
- Não há necessidade de finalizar processos que usam pouca memória.
- Você precisa concluir um mínimo de processos.
- 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.