OOM Killer - servidor MySQL morto

10

Em um de nossos mestres no MySQL, o OOM Killer foi chamado e matou o servidor MySQL, o que levou a uma grande interrupção. A seguir está o log do kernel:

[2006013.230723] mysqld invoked oom-killer: gfp_mask=0x201da, order=0, oom_adj=0
[2006013.230733] Pid: 1319, comm: mysqld Tainted: P           2.6.32-5-amd64 #1
[2006013.230735] Call Trace:
[2006013.230744]  [<ffffffff810b6708>] ? oom_kill_process+0x7f/0x23f
[2006013.230750]  [<ffffffff8106bde2>] ? timekeeping_get_ns+0xe/0x2e
[2006013.230754]  [<ffffffff810b6c2c>] ? __out_of_memory+0x12a/0x141
[2006013.230757]  [<ffffffff810b6d83>] ? out_of_memory+0x140/0x172
[2006013.230762]  [<ffffffff810baae8>] ? __alloc_pages_nodemask+0x4ec/0x5fc
[2006013.230768]  [<ffffffff812fca02>] ? io_schedule+0x93/0xb7
[2006013.230773]  [<ffffffff810bc051>] ? __do_page_cache_readahead+0x9b/0x1b4
[2006013.230778]  [<ffffffff810652f8>] ? wake_bit_function+0x0/0x23
[2006013.230782]  [<ffffffff810bc186>] ? ra_submit+0x1c/0x20
[2006013.230785]  [<ffffffff810b4e53>] ? filemap_fault+0x17d/0x2f6
[2006013.230790]  [<ffffffff810cae1e>] ? __do_fault+0x54/0x3c3
[2006013.230794]  [<ffffffff812fce29>] ? __wait_on_bit_lock+0x76/0x84
[2006013.230798]  [<ffffffff810cd172>] ? handle_mm_fault+0x3b8/0x80f
[2006013.230803]  [<ffffffff8103a9a0>] ? pick_next_task+0x21/0x3c
[2006013.230808]  [<ffffffff810168ba>] ? sched_clock+0x5/0x8
[2006013.230813]  [<ffffffff81300186>] ? do_page_fault+0x2e0/0x2fc
[2006013.230817]  [<ffffffff812fe025>] ? page_fault+0x25/0x30

Esta máquina possui 64 GB de RAM.

A seguir estão as variáveis ​​de configuração do mysql:

innodb_buffer_pool_size        = 48G
innodb_additional_mem_pool_size = 512M
innodb_log_buffer_size         = 64M

Exceto alguns plug-ins e scripts de coleção de métricas do nagios, nada mais roda nesta máquina. Alguém pode me ajudar a descobrir por que o OOM killer foi invocado e como posso impedir que ele seja invocado no futuro. Existe alguma maneira de dizer ao OOM killer para não matar o servidor mysql. Eu sei que podemos definir um oom_adjvalor muito menor para um processo para impedir que ele seja morto pelo assassino do OOM. Mas existe outra maneira de evitar isso.

pradeepchhetri
fonte
2
O uso da memória será maior que 48G+ 512M+ 64Mporque também há algumas sobrecargas e outras estruturas a serem consideradas; havia uma fórmula para isso em algum lugar, mas não consigo encontrá-la agora. Não tenho certeza se isso faria com que ele explodisse o 64G. Apenas para ter certeza, freeconfirma que 64Gestão disponíveis em primeiro lugar?
frostschutz 12/11/2013
@frostschutz: sim, o comando free mostra 64G.
Pradeepchhetri 12/11/2013
Dizer ao OOM Killer para não matar o mysqld provavelmente atrasará o desastre por um breve momento. Corrija melhor sua configuração.
Scai

Respostas:

25

Linux faz overcommit de memória. Isso significa que ele permite que o processo solicite mais memória do que realmente está disponível no sistema. Quando um programa tenta malloc (), o kernel diz "OK, você conseguiu a memória", mas não a reserva. A memória será reservada apenas quando o processo escrever algo neste espaço.

Para ver a diferença, você tem 2 indicadores: Memória virtual e Memória residente. Virtual é a memória solicitada pelo processo, Residente é a memória realmente usada pelo processo.

Com este sistema, você pode entrar em "overbooking", o kernel concede mais memória do que o disponível. Então, quando seu sistema passa a 0 byte de memória livre e troca, ele deve sacrificar (matar) um processo para obter memória livre.

É quando o OOM Killer entra em ação. O OOM seleciona um processo baseado em seu consumo de memória, e muitos outros elementos (ganhos pais 1/2 da pontuação dos seus filhos, se é um processo raiz de propriedade, o resultado é dividido por 4, etc .. Dê uma olhada em Linux- MM.org/OOM_Killer

Você pode influenciar a pontuação do OOM, ajustando o /proc/MySQL_PID/oom_adjarquivo. Ao defini-lo como -17, seu processo nunca será eliminado. Mas antes de fazer isso , você deve ajustar seu arquivo de configuração do MySQL para limitar o uso da memória do MySQL. Caso contrário, o OOM Killer matará outro processo do sistema (como SSH, crontab, etc ...) e o servidor estará em um estado muito instável, talvez levando a corrupção de dados, pior do que qualquer coisa.

Além disso, você pode considerar o uso de mais trocas.

[EDITAR]

Você também pode alterar seu comportamento de supercomprometimento por meio desses 2 sysctls:

vm.overcommit_memory
vm.overcommit_ratio

Conforme declarado na Documentação do Kernel

overcommit_memory:

Este valor contém um sinalizador que permite o comprometimento excessivo da memória.

Quando esse sinalizador é 0, o kernel tenta estimar a quantidade de memória livre restante quando o espaço do usuário solicita mais memória.

Quando esse sinalizador é 1, o kernel finge que sempre há memória suficiente até que realmente se esgote.

Quando esse sinalizador é 2, o kernel usa uma diretiva "nunca comprometer demais" que tenta impedir o comprometimento excessivo da memória. Observe que user_reserve_kbytes afeta esta política.

Esse recurso pode ser muito útil porque existem muitos programas que malocultam grandes quantidades de memória "just-in-case" e não a utilizam muito.

O valor padrão é 0.

Consulte Documentação / vm / overcommit-accounting and security / commoncap.c :: cap_vm_enough_memory () para obter mais informações.

overcommit_ratio:

Quando overcommit_memory é definido como 2, o espaço de endereço confirmado não pode exceder a troca mais essa porcentagem de RAM física. Veja acima.

[/EDITAR]

Adrien M.
fonte
1
Esta é a resposta certa. Eu tenho visto artigos sobre como usar isso oom_score_adjpara corrigir isso, mas eles realmente não entendem o mecanismo de pontuação.
3manuek