OOM Killer - matou o servidor MySQL

11

Em um dos nossos mestres MySQL, OOM Killer foi invocado 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 tem 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 dos scripts de plugins e coleta de métricas do nagios, nada mais é executado nesta máquina. Alguém pode me ajudar a descobrir por que o killer da OOM foi chamado e como posso evitar que ele seja chamado no futuro? Existe alguma maneira eu posso dizer killer OOM para não matar o servidor mysql. Eu sei que podemos definir oom_adj valor para muito menos para um processo para evitar que ele seja morto pelo assassino de OOM. Mas existe alguma outra maneira de evitar isso?

    
por pradeepchhetri 12.11.2013 / 10:39

1 resposta

26

O Linux supercomprime a memória. Isso significa que permite que o processo solicite mais memória do que realmente disponível no sistema. Quando um programa tenta malloc (), o kernel diz "OK, você pegou a memória", mas não a reserva. A memória só será reservada quando o processo escrever algo nesse 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 a disponível. Então, quando seu sistema ficar com 0 byte de memória livre e Swap, ele deve sacrificar (matar) um processo para ganhar 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 (o pai ganha 1/2 da pontuação de seus filhos; se for um processo de propriedade da raiz, a pontuação é dividida por 4, etc. Dê uma olhada em Linux-MM.org/OOM_Killer

Você pode influenciar na pontuação da OOM, sintonizando o arquivo /proc/MySQL_PID/oom_adj . 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 de memória do MySQL. Caso contrário, o OOM Killer matará outro processo do sistema (como SSH, crontab, etc ...) e seu servidor estará em um estado muito instável, talvez levando a corrupção de dados , que é pior do que qualquer coisa.

Além disso, você pode considerar usar mais troca.

[EDITAR]

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

vm.overcommit_memory
vm.overcommit_ratio

Como declarado em Documentação do Kernel

overcommit_memory:

This value contains a flag that enables memory overcommitment.

When this flag is 0, the kernel attempts to estimate the amount of free memory left when userspace requests more memory.

When this flag is 1, the kernel pretends there is always enough memory until it actually runs out.

When this flag is 2, the kernel uses a "never overcommit" policy that attempts to prevent any overcommit of memory. Note that user_reserve_kbytes affects this policy.

This feature can be very useful because there are a lot of programs that malloc() huge amounts of memory "just-in-case" and don't use much of it.

The default value is 0.

See Documentation/vm/overcommit-accounting and security/commoncap.c::cap_vm_enough_memory() for more information.

overcommit_ratio:

When overcommit_memory is set to 2, the committed address space is not permitted to exceed swap plus this percentage of physical RAM. See above.

[/ EDIT]

    
por 12.11.2013 / 11:48