
OOM Killer(Out of Memory Killer)는 시스템이 실제 메모리와 가상 메모리 공간(스왑)을 다 사용해, 필요한 메모리 공간을 새로 확보 할 수 없는 경우 프로세스를 종료시켜 여유 메모리를 확보하는 Linux 커널의 메커니즘 중에 하나이다.
그래서 kill된 프로세스가 자기가 왜 죽어버리는지 알수 없는 인터럽트가 발생해서 자신이 인터럽트가 발생했을 때 예외처리를 수행하지 못하는 문제가 발생한다. 이런 현상이 데이터를 관리하는 DB 서버에서 발생한다면 Linux의 좋은 매커니즘이라도 고객의 인지 정보가 실제 데이터에는 저장되지 않는 데이터 유실을 유발시킬 수 있다. DB 자체가 메모리 부족을 인지하고 예외처리하는 로직을 테우게 OS환경을 만들어줄 필요가 있다.
사소하지만 고민해야할 부분인 것이다.
관련 커널 메개변수 정보를 설명하면..
*. vm.overcommit_memory- 0 : heuristic에 따라 overcommit 할 수 있고, 하지 않을 수도 있다.(디폴트) 메모리 요구가 있을 때 여유 공간이 없는 경우 실행중인 프로세스를 강제 종료 메모리를 억지로 확보함.
- 1 : 항상 overcommit 함. 메모리를 다 사용했는데도 충분한 메모리가있는 것처럼 처리 됨. 그 외에는 0과 같음.
- 2 : overcommit하지 않음. 메모리가 부족할 경우 메모리 확보시 에러 발생시킴. [Swap size] + ([RAM size] * vm.overcommit_ratio/100).
- 사용 가능한 메모리의 백분율로 정의. overcommit_ratio의 디폴트는 50.
vm.overcommit_memory = 0 or 1 일 경우 현재 환경에서 메모리 확보 테스트해 보면
현재의 메모리 정보는 아래와 같다.[root@mimul01 ~]# free total used free shared buffers cached Mem: 1019680 457172 562508 0 25384 159084 -/+ buffers/cache: 272704 746976 Swap: 0 0 0
Physical Memory는 1G정도 된다고 볼 수 있다. CommitLimit(상한)과 Committed_AS(사용량) 정보는 아래와 같다.
[root@mimul01 ~]# cat /proc/meminfo |grep Comm CommitLimit: 1009480 kB Committed_AS: 518468 kB
그런 다음 아래 소스를 가지고 malloc 테스트를 실행 해 보았다. 이 경우 오버커밋이 허용되어 있어서 malloc_test 프로그램이 구동되는 동안 계속 메모리 확보를 하고 오버커밋된 범위까지도 메모리 할당을 시도한다. 즉 malloc에서 에러 리턴을 하지 않는 구조이다.
> cat malloc_test.c #include <stdio.h> #include <stdlib.h> #define KB 1024 #define MB (1024*KB) int main() { int i = 0; char *ptr = NULL; for (i=0; ;i++) { ptr = (char *)malloc(MB); if(ptr == NULL){ break; } } printf("MALLOC SIZE=%dMB\n",i); return(0); } [mimul01]/home/k2/Downloads/alloctest> gcc -o malloc_test malloc_test.c [mimul01]/home/k2/Downloads/alloctest> ./malloc_test 죽었음
오버커밋 처리되어 malloc_test에서 인터럽트되어 제어가 되지 않고 OOM-killer에 의해 프로세스가 죽게 된다. 이럴 경우 malloc_test 프로세스는 내부의 예외처리가 무시되어 중요한 문제에 봉착될 수 있다. 아래는 프로세스가 죽었을 때 로그이다.
May 8 11:18:50 mimul01 kernel: Out of memory: Kill process 3121 (malloc_test) score 884 or sacrifice child
vm.overcommit_memory = 2, vm.overcommit_ratio = 99 일 경우 테스트 사례는
CommitLimit(상한)과 Committed_AS(사용량) 정보는 아래와 같다.[mimul01]/home/k2/Downloads/alloctest> cat /proc/meminfo |grep Comm CommitLimit: 1009480 kB Committed_AS: 520128 kB
이경우에는 아래처럼 정보를 보면 알겠지만 malloc시 널로 리턴되어 거기까지 메모리를 할당하고 빠져나오는 프로그램 프로세스를 그대로 탔다. 이처럼 제어가 프로그램으로 넘어거 예외 처리를 할 수 있는 구조가 된다.
[mimul01]/home/k2/Downloads/alloctest> ./malloc_test MALLOC SIZE=433MB
특히나 대상 서버가 데이터 베이스 서버일 경우에는 데이터의 무결성이 중요함으로 MySQL 데몬에 의해 예외 프로세스를 타게 해주는 것이 유효해 보인다.
더 중요한건 서버의 자원 모니터링을 해서 부족하지 않도록 Scale Up을 잘 해 주는 것이 필요하다.
결론은..
데이터 베이스 서버(MySQL, PostGreSQL, Redis 등)일 경우에는 커널 정보에 아래 설정을 해 두는 것이 데이터 무결성 보호에 도움을 받을 것이다.vm.overcommit_memory = 2 vm.overcommit_ratio = 99
그리고 데이터 베이스 서버는 스왑 사용도 비용이 크므로 vm.swappiness = 0로 운영하는 것도 괜찮다.