OOM Killer-MySQL 서버 종료 ? __alloc_pages_nodemask+0x4ec/0x5fc [2006013.230768]

MySQL 마스터 중 하나에서 OOM Killer가 MySQL 서버를 호출하고 종료하여 큰 중단을 초래했습니다. 다음은 커널 로그입니다.

[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

이 기기에는 64GB RAM이 있습니다.

다음은 mysql 구성 변수입니다.

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

일부 nagios 플러그인 및 메트릭 수집 스크립트를 제외하고이 시스템에서 다른 것은 실행되지 않습니다. 누군가 OOM killer가 호출 된 이유와 나중에 호출되는 것을 방지 할 수있는 방법을 알려줄 수 있습니까? OOM 킬러에게 mysql 서버를 죽이지 말라고 말할 수있는 방법이 있습니까? oom_adj프로세스가 OOM 킬러에 의해 죽지 않도록 프로세스에 대해 값을 매우 작게 설정할 수 있다는 것을 알고 있습니다 . 그러나 이것을 방지하는 다른 방법이 있습니까?



답변

리눅스는 메모리 오버 커밋을한다. 즉, 프로세스가 시스템에서 실제로 사용 가능한 것보다 많은 메모리를 요청할 수 있습니다. 프로그램이 malloc ()을 시도 할 때 커널은 “OK you have a memory”라는 메시지를 표시하지만 예약하지는 않습니다. 프로세스가이 공간에 무언가를 쓸 때만 메모리가 예약됩니다.

차이점을 확인하기 위해 가상 메모리와 상주 메모리라는 두 가지 표시기가 있습니다. 가상은 프로세스가 요청한 메모리이고, 상주는 프로세스가 실제로 사용하는 메모리입니다.

이 시스템을 사용하면 커널이 사용 가능한 것보다 많은 메모리를 부여하는 “과다 예약”으로 들어갈 수 있습니다. 그런 다음 시스템이 0 바이트의 사용 가능한 메모리와 스왑을 수행하면 사용 가능한 메모리를 확보하기 위해 프로세스를 희생 (kill) 해야합니다 .

그때 OOM Killer가 작동합니다. OOM은 메모리 소비 및 기타 많은 요소 (부모가 자녀 점수의 1/2을 얻습니다. 루트 소유 프로세스 인 경우 점수는 4로 나뉩니다.)를 기준으로 프로세스를 선택합니다. Linux를 살펴보십시오. MM.org/OOM_Killer

/proc/MySQL_PID/oom_adj파일 을 조정하여 OOM 점수에 영향을 줄 수 있습니다 . 로 설정하면 -17프로세스가 종료되지 않습니다. 그러나 그렇게 하기 전에 MySQL 메모리 사용을 제한하기 위해 MySQL 구성 파일조정 해야 합니다. 그렇지 않으면 OOM Killer가 다른 시스템 프로세스 (SSH, crontab 등과 같은)를 종료하고 서버가 매우 불안정한 상태가되어 데이터 손상으로 이어질 수 있습니다.

또한 더 많은 스왑 사용을 고려할 수 있습니다.

[편집하다]

다음 2 개의 sysctls를 통해 초과 커밋 동작을 변경할 수도 있습니다.

vm.overcommit_memory
vm.overcommit_ratio

커널 문서에 명시된 바와 같이

overcommit_memory :

이 값에는 메모리 초과 커밋을 활성화하는 플래그가 포함됩니다.

이 플래그가 0이면, 커널은 사용자 공간이 더 많은 메모리를 요청할 때 남은 여유 메모리의 양을 추정하려고 시도합니다.

이 플래그가 1이면 커널은 실제로 부족할 때까지 항상 충분한 메모리가있는 것으로 가장합니다.

이 플래그가 2 인 경우, 커널은 “과도하게 커밋하지 않음”정책을 사용하여 메모리가 너무 커밋되지 않도록합니다. user_reserve_kbytes는이 정책에 영향을 미칩니다.

이 기능은 malloc () 방대한 양의 메모리가 “경우에 따라”많은 프로그램을 사용하지 않기 때문에 매우 유용 할 수 있습니다.

기본값은 0입니다.

자세한 내용은 Documentation / vm / overcommit-accounting 및 security / commoncap.c :: cap_vm_enough_memory ()를 참조하십시오.

overcommit_ratio :

overcommit_memory를 2로 설정하면 커밋 된 주소 공간이 스왑 +이 백분율의 실제 RAM을 초과 할 수 없습니다. 위 참조.

[/편집하다]


답변