Database 를 위한 공유 메모리, HugePages 계산하기
Database 시스템은 공유메모리 혹은 HugePages 에 매우 의존적입니다. 서버에서 데이터베이스가 가동되면 Database 가 사용하는 메모리는 Database만을 위해서 사용되어 집니다. 대부분의 큰 Database 시스템은 다른 서버 프로그램 없이 단독으로 설치되어 운영되어지기 때문에 얼마만큼 물리적 메모리를 Database 에 할당할지가 Database 시스템 전체에 큰 영향을 미칩니다.
이 글에서 Database 시스템을 위한 공유메모리, HugePages 등을 할당할때에 고려사항은 무엇이며 얼마나 할당하는 것이 좋은지를 살펴보겠습니다.
Oracle 11g or 12c
먼저 Oracle 은 물리적 메모리에 약 80% 를 Oracle 이 사용하도록 할당하도록 합니다. 여기서 대략 80% 라고 했는데, 만일 몇가지 프로그램을 함께 돌린다면 약 75% 가 적당합니다.
물리 메모리의 약 80% 할당
여기서 고려해야할 사항이 하나 있습니다. 80%를 할당하라고 해서 무조건 80%를 할당하게 되면 문제가 됩니다. 예를들어 16GB 의 물리 메모리로 운영하는 경우에 80%면 12.8GB 이고 서버에서 사용가능한 용량은 3.2GB 입니다. 요새 데스크탑 컴퓨터도 안되도 4GB 는 사용하는데 아무리 가벼운(?) 리눅스 서버라도 3.2GB 는 운영하는데 너무 적어 보입니다.
이럴때는 운영체제에서 사용할 최소 메모리를 남겨두고 나머지를 Oracle 에 할당하는게 현명하다고 할 수 있습니다.
또하나 중요하게 고려해야할 사항은 Oracle 에서 AMM을 쓰느냐 안쓰느냐 하는 문제 입니다. 이 둘의 차이는 다음과 같습니다.
AMM 을 사용할 경우: /dev/shm 장치를 이용한 공유메모리 모델 사용. HugePages 사용 불가
AMM을 사용하지 않을 경우: System V 공유 메모리 모델 사용. HugePages 사용 가능
Oracle 11g 버전으로 넘어오면서 전에 없던 기능이 하나 생겼는데, 그것은 바로 AMM(Aotomactic Memory Management) 입니다. AMM은 Oracle의 메모리 모델인 SGA와 PGA 를 통틀어서 메모리 관리를 자동으로 해준다는 개념입니다.
AMM 기능을 이용하면 대략적으로 SGA 영역은 Oracle 할당받은 메모리 영역에서 85%, PGA 는 약 15%로 나눠서 관리한다고 합니다.
또 한가지 AMM의 특징이 있는데, 공유메모리 모델중에서 /dev/shm 장치를 이용한 Posix 규격의 공유메모리 모델을 사용한다고 합니다. 이 메모리 모델은 메모리 가상 장치를 통해서 프로세스가 공유할 내용을 파일로 저장해서 공유하는 방법으로 오로지 용량에만 제약사항이 있습니다. 공유할 내용을 파일로 생성할때에 얼마만한 크기로 생성할지는 전적으로 서버 프로그램, 여기서는 Oracle, 에 의해서 결정됩니다. 최근의 모든 리눅스 서버는 /dev/shm 이 자동으로 마운트되어 있으며 기본적으로 전체 물리메모리의 50%를 사용합니다.
용량을 바꾸기 위해서는 다음과 같이 해줍니다. CentOS 6과 CentOS 7 배포판 별로 차이가 조금 있습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
## CentOS 6 umount /dev/shm mount -t tmpfs shmfs -o size=4g /dev/shm ## /etc/fstab - tmpfs /dev/shm tmpfs defaults 0 0 + tmpfs /dev/shm tmpfs defaults,size=12G 0 0 ## Apply changes of /dev/shm mount -o remount /dev/shm ## CentOS 7 ## /etc/fstab + shmfs /dev/shm tmpfs defaults,size=12G 0 0 ## Apply changes of /dev/shm mount -o remount /dev/shm |
만일 AMM을 사용하지 않을 경우에는 SystemV 의 공유메모리 설정을 따르게 됩니다. 이때에 HugePages 도 함께 사용할 수 있습니다. 이 설정들은 커널 파라메터로 조정하며 그 설정 변수는 다음과 같습니다.
shmmax: 단일 프로세스가 공유메모리를 호출하기 위한 최대 값. 단위 Bytes
shmall: 시스템을 통틀어 사용가능한 공유 메모리 Page 량. 단위 Page
nr_hugepages: Huge 페이지 개수.
여기서 중요한 것이 만일 HugePages 를 사용한다면 shmall 은 사용되지 않습니다. shmall 은 리눅스 메모리의 기본단위인 4096bytes(4k) 를 기반으로 계산되어 지는데, HugPages 는 이보다 더 큰 2048k(2MB) 를 기반으로 페이지를 나누기 때문입니다.
어찌됐든 이런 모든 상황을 고려해서 사용가능한 메모리를 구한다면 다음과 같은 공식으로 구할 수 있습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
#!/bin/sh # # if [ -z $1 ]; then echo "Usage: shm_setup.sh size(MB)" exit 1 fi DB_MEMORY=$(($1+500)) PAGE=$(getconf PAGESIZE) HUGEPAGE=$(cat /proc/meminfo |grep -i Hugepagesize|awk '{print $2}') echo "Actually For DB memory has about 100MB bigger than $1 Totally DB's Memory is $DB_MEMORY MB" if [ $DB_MEMORY -le '500' ]; then echo "DB's Memory should be greater than 500MB" exit 1 else echo "PAGESIZE: $PAGE" echo "HugePage Size: $HUGEPAGE" echo "" echo "kernel.shmmax = $(($DB_MEMORY*1024*1024))" echo "kernel.shmall = $((($DB_MEMORY*1024*1024)/$PAGE))" echo "vm.nr_hugepages = $(($DB_MEMORY/($HUGEPAGE/1024)))" echo "@oinstall soft memlock = unlimited" #echo "@oinstall soft memlock = $(($DB_MEMORY*1024))" echo "@oinstall hard memlock = unlimited" #echo "@oinstall hard memlock = $(($DB_MEMORY*1024))" fi |
보시면 아시겠지만 다른분이 만들어놓은 것으로 최소 500MB 용량을 넘는 것으로해서 shmmax, shmall, hugepages 를 모두 계산하고 있습니다.
MySQL 5.x
MySQL 의 경우에, InnoDB 엔진만을 사용한다는 전제하에, 전체 메모리의 80%를 MySQL이 할당해서 사용하도록 설정합니다.
물리 메모리의 약 80%를 MySQL에 할당(InnoDB만 사용)
MySQL 은 오로지 SystemV 의 공유메모리 모델을 따릅니다. 따라서 HugePages 를 사용할 수 있는데, 이를 위해서는 다음과 같이 my.cnf 에 설정을 해줘야 합니다.
1 2 |
[mysqld] large-pages |
그리고 shmmax,shmall,nr_hugepages 는 앞에 스크립트를 이용해서 구합니다.
Linux 설정
SystemV 공유 메모리 모델의 경우에 몇가지를 더 해줘야 합니다.
첫째로 Transparent Huge Pages (THP) 설정을 꺼야 합니다. 성능저하가 발생한다고 하네요. 다음과 같이 간단히 처리 할 수 있습니다.
1 2 |
echo never > /sys/kernel/mm/transparent_hugepage/enabled echo never > /sys/kernel/mm/transparent_hugepage/defrag |
매번 부팅시마다 자동으로 설정하고 싶다면 부팅 파라메터를 수정해 줍니다.
Ubuntu 의 경우에는 다음과 같이 해줍니다.
1 2 3 4 |
# vim /etc/default/grub - GRUB_CMDLINE_LINUX="net.ifnames=0 biosdevname=0" + GRUB_CMDLINE_LINUX="net.ifnames=0 biosdevname=0 transparent_hugepage=never" # update-grub2 |
CentOS 의 경우에는 다음과 같이 해줍니다.
1 2 3 4 |
# vim /etc/default/grub - GRUB_CMDLINE_LINUX="crashkernel=auto rhgb quiet" + GRUB_CMDLINE_LINUX="crashkernel=auto rhgb quiet transparent_hugepage=never" # update-grub2 |
확인도 가능한데, 다음과 같이 AnonHugePages 값이 0Kb 명 THP 가 비활성화 된 것입니다.
1 2 |
]# grep Huge /proc/meminfo AnonHugePages: 0 |
마지막으로 커널이 HugePage 를 사용할 그룹이 누군지를 지정해 줍니다.
1 |
vm.hugetlb_shm_group = `id -g mysql` |
위와같이 리눅스 시스템 사용자의 그룹ID 를 알아내도록 명령어를 입력할 수도 있고 아니면 그냥 그룹ID를 찾아서 적어줘도 됩니다.