Oracle, MariadB, MySQL 등과 같은 관계형 데이터베이스를 다루다보면 시스템 튜닝에 대해서 많이 접하게 된다. 특히나 리눅스 시스템에서 이들 데이터베이스 시스템이 제대로 작동하기 위한 운영체제 차원에서 필요한 작업을 많이 하게 된다.
이러한 운영체제 차원에서 작업은 여러가지가 있어서 알아야 하는 내용도 많고 세팅해야 하는 것도 많다. 대부분 인터넷이나 가이드 북을 이용해 어찌어찌 설정을 한다고 하지만 많은 사람들이 그것이 왜 필요한지 깊게 이해하는 사람들은 드물다.
그래서 아주 간단하게 데이터베이스 시스템을 다루는데 있어 리눅스 운영체제에서 필요로 하는 작업에 필요한 배경지식에 대해서 다루어 보고자 한다.
가상 메모리 관리(Virtual Memory Management)
모든 운영체제는 가상 메모리 관리 기법을 사용한다. 가상이라는 말에서 보이듯이 메모리를 가상화 한다는 이야기인데, 정확하게 말하면 실제로 물리적 메모리의 양이 정해져 있는데도 불구하고 그보다 많은 메모리를 필요로하는 애플리케이션을 구동할 수 있게 해주는 기법이다.
가상 메모리 관리 기법이 존재하기 전에는 실제 물리적 메모리 보다 많은 애플리케이션을 실행할 수 없었다. 더군다나 현대의 운영체제는 멀티 태스킹(Multi Tasking) 으로 운영되기 때문에 이들 애플리케이션 모두가 사용하는 메모리 양을 계산해보면 실제 물리적 메모리보다 많다. 그런데도 신기하게도 아무런 문제 없이 작동되는데 가상 메모리 기법 때문이다.
가상 메모리 관리에서 운영체제는 실제 주소가 아닌 가상 메모리 주소에 접근하게 된다. 하지만 실제 데이터는 물리적 메모리에 존재하기 때문에 가상 메모리 주소를 물리적 메모리로 변환해줘야 할 필요가 있다. 이렇게 가상 메모리 주소를 물리적 메모리 주소로 변환해주는 것이 MMU(Memory Management Unit) 이다.
이 MMU 는 물리적으로 CPU 내부에 존재한다. 현대의 거의 대부분의 CPU 에는 이런 MMU 가 다 있다.
MMU 는 가상 메모리 주소를 실제 물리적 주소로 변환해주는 것인데, 내부적으로 가상 메모리 주소와 물리적 주소를 매핑 시켜놓는 테이블이 존재한다.
일종의 매핑 테이블(Mapping Table) 인데 매핑 테이블은 가상 메모리 주소와 물리 메모리를 페이지(Page) 단위로 관리하도록 되어 있다. 쉽게 말하면 가상 메모리 주소 공간을 특정 크기 단위로 쪼갠 페이지, 실제 물리 메모리 주소를 특정 크기 단위로 쪼갠 페이지를 서로 매핑 시켜 논 것이다.
위 그림을 보면 가상 메모리, 물리 메모리가 양 옆에 있고 중간에 주소변환을 위한 페이지 맵(PAGE MAP) 혹은 테이블 이 존재한다.
MMU 느린 속도
MMU 내에 페이지 테이블이 존재는 가상 메모리를 물리 메모리로 빠르게 변환 시켜준다. MMU가 CPU 내부, 반도체 내부에 유닛으로 존재하다보니 소프트웨어에 비하면 속도가 매우 빠르다.
그런데, CPU 에서 가상 메모리에 접근할때 마다 페이지 테이블 전체를 스캔해야 한다. 그래야만 실제 데이터를 가지고 올 수 있을 테니까. 아무리 반도체 칩으로 구현되어 있어도 이렇게 데이터 접근시마다 페이지 테이블 전체를 스캔하면 아무해도 속도가 나질 않는다.
만일 페이지 테이블이 엄청나게 크다면 이 또한 속도에 영향을 준다.
느린 속도… 캐쉬가 답이다.
그래서 MMU 에 페이지 테이블 검색 속도를 높이기 위해서 중간에 캐쉬를 놓게 되었는데 이것이 바로 TLB(Translation Lookaside Buffer) 이다.
위 그림은 가상 메모리 접근에 MMU 내부의 페이지 테이블과 TLB 가 작동하는지를 보여주는 그림이다. 간단하게 설명하면 CPU 는 무조건 TLB 를 먼저 찾는다. 캐쉬이다 보니까 필요로하는 데이터가 TLB 에 접근하면 찾을 수 있는지 검색을 하는 것이다. 만일 있다면 TLB 를 이용해서 물리 메모리에 접근하게 된다.
하지만 TLB 에 없다면 그때는 페이지 테이블을 전부 스캔하게 된다. 이렇게 페이지 테이블 스캔은 전체적으로 메모리 접근 속도에 영향을 주게 되고 전체적인 운영체제 성능에 영향을 미치게 된다.
4kb 크기의 페이지 문제
리눅스 운영체제에서 한 페이지 단위는 4kb 크기다. 만일 128GB 의 물리 메모리를 장착할 경우에 32M(약 3천 2백만) 개 정도의 페이지가 존재하게 된다. 이 많은 페이지를 페이지 테이블에 쑤셔 넣고 전체 스캔을 하게 되면 아무리 빠른 CPU라도 느릴 수밖에 없게 된다.
또한, 많은 양의 페이지는 TLB 에도 영향을 주게 된다. 너무나 많은 페이지가 존재 하다보니 캐쉬를 했던 페이지의 hit 율이 떨어져 자꾸 페이지 테이블 스캔을 하게 되는 것이다.
페이지 테이블이 페이지가 적고 캐쉬해야하는 양이 많으면 페이지 테이블를 스캔해야하는 일이 줄어든다.
HugePage 는 TLB 의 Hit 를 높여준다
Huge Page 는 기본 페이지 크기 4kb 를 크게 하는 기법이다. 이 기법을 사용하면 페이지 갯수가 줄어든다.
그런데, 많은 사람들이 페이지 크기를 늘리게 될 경우에 그 페이지가 가지는 데이터의 양을 한꺼번에 접근할 수 있어서 효율이 높아진다고 생각하는 경우가 많다. 물론 그런 영향이 없지는 않지만 Huge Page 를 하는 이유는 TLB 의 Hit 를 높여주는, 반대로 TLB 의 Miss 를 낮춰주는데 있다.
TLB 의 Hit 를 높여주면, 캐쉬 사용을 높여주면 데이터 접근이 빨라진다. 이것은 전체적인 운영체제의 메모리 성능을 높여주는 효과를 보여주게 된다. TLB Hit 를 위해서 간단한 방법이 바로 페이지 크기를 늘려주는 것이다. 4kb 마다 한 페이지가 아닌 2MB 마다 한 페이지라면 페이지 테이블 크기도 줄어들고 TLB 에 캐쉬된 페이지의 Hit 가 높아지게 된다.
Huge Page 사용 전략
HugePage 를 무턱대고 설정해서는 안된다. 일종의 전략이 반드시 필요하다.
OS 에서 지원해 줘야 한다.
애플리케이션에서 지원해 줘야 한다.
공유 메모리 설정과 연계되어 있다.
HugePage 를 사용하면 무조건 OS 상에 성능이 개선되는게 아니다. OS 에서는 당연히 사용을 하겠지만 애플리케이션에서도 HugePage 사용이 가능해야 한다.
HugePage 가 사용 가능한 애플리케이션으로 데이터베이스 시스템이 있다. PHP 와 같은 경우에도 사용이 가능하다고 한다.
무엇보다 중요한 것은 HugePage 설정은 단일 애플리케이션 시스템에 적합하다. Oracle 데이터베이스 하나만 작동하는 시스템이나 MySQL 하나만 작동하는 시스템등 여러 애플리케이션이 아니라 단일 애플리케이션만 구동하는 환경이라야 한다.
리눅스에서 HugePage 설정
MariaDB 를 위해 설정을 진행 해보자. 환경은 다음과 같다.
CentOS 8 64bit
RAM 4G
MariaDB 10.5.8
가장 먼저 해야할 것은 Transparent Huge Pages (THP) 설정을 never 로 바꾸는 것이다. THP 는 HugePage 를 자동으로 맞춰주는 기능인데, 성능 하락을 가져오기도 한다.
커널 파라메터를 수정하는 방법도 있지만 grub 에 부팅 옵션을 추가하는 것이 가장 간단하다.
]# grub2-mkconfig -o /boot/efi/EFI/centos/grub.cfg # EFI Bios 경우
위와같이 한 다음 재부팅을 한번 해주면 적용 된다.
현재 상태를 살펴보자. /proc/meminfo 를 보면 알 수 있다.
HugePage 사용 확인
ZSH
1
2
3
4
5
6
7
]$grep-i'^Huge'/proc/meminfo
HugePages_Total:0
HugePages_Free:0
HugePages_Rsvd:0
HugePages_Surp:0
Hugepagesize:2048kB
Hugetlb:0kB
내용을 보면 아직 HugPage 를 사용하고 있지 않다고 나온다. 여기서 이제 계산이 필요하다. 얼마만큼 사용할 것인가, 누가 사용할 것인가 결정해야 하는 것이다.
MariaDB 를 사용할 것인데, MariaDB 를 사용하는데 있어서 InnoDB 를 사용할 것이다. InnoDB 는 Innodb pool 이 주로 메모리를 사용할 것인데, MariaDB 의 경우 물리 메모리에 약 70% 를 Inndb Pool 로 할달할 것을 권고 하고 있다. 나머지 10%는 MariaDB 자체 운영을 위해서 필요 하다. 전체 물리메모리에 약 80%에 해당한다.
df -k 했을때 나오는 전체 메모리 양이 3825740 kb(약 3.8GB) 인데, 이것에 80% 이면 3060592 kb 이다. 이것을 다시 2048 kb (한 페이지 크기) 로 나누면 1494.4296875 인데, 대략 1500 정도로 해두면 될 듯 하다.
이것을 이제 커널 파라메터로 넘겨 준다. sysctl.d 디렉토리에 파일을 만들어 별도로 관리해준다.
HugePage 설정
ZSH
1
2
3
4
5
]# vim /etc/sysctl.d/10-memory.conf
vm.nr_hugepages=1500
# vm.hugetlb_shm_group=27
]# sysctl --load /etc/sysctl.d/10-memory.conf
vm.nr_hugepages=1500
vm.hugetlb_shm_group 은 hugetlb 를 사용할 리눅스 시스템 그룹을 지정한 것이다.
MariaDB 에서 설정하기
시스템에서 HugePage 사용을 설정했다고 MariaDB 가 알아서 사용하지 않는다. my.cnf 서버 설정 파일에서 사용하도록 지정해 줘야 한다.
galera_recovery 라는 명령어가 있다. 이 파일을 쉘 스크립트 파일인데, mariadb.service 파일에도 이 명령어가 사용되고 있다. 그런데, 이 파일에는 사용지로 mysql 로 하드코딩되어 있어서 오류를 낸다. 바꿔준다.
galera_recovery 파일 수정
diff
1
2
- user=mysql
+ user=mariadb
systemd 등록
Mariadb 에서는 systemd 등록을 위한 서비스 유닛 파일을 제공한다. 이 파일은 설치 디렉토리에 support-files/systemd 에 mariadb.service 파일로 존재한다. 이 파일을 열어서 mariadb 실행 계정과 그룹을 다음과 같이 바꿔 준다.
MySQL 은 인기있는 오픈소스 데이터베이스 시스템이다. 언제나 데이터베이스 시스템이라면 항상 따라오는 것이 Master-Slave 리플리케이션 환경이고 거기에 덧붙여 자동 페일오버(Auto FailOver) 를 어떻게 할 것이라는 골머리 앓는 주제가 따라서 나온다.
MySQL 의 경우에 자체 적인 FailOver 솔루션이 있다. Fabric 이 그것인데, 아직은 많이 쓰이지는 않는 모양이다. 대신에 AutoFailOver 를 지원하는 제3의 툴들이 존재하는데 M-HA 가 바로 이러한 솔루션이다.
M-HA 는 일본인이 Perl 을 이용해서 작성한 솔루션이다. github 저장소에 소스코드는 공개되어 있으며 저장소이름은 mha4mysql-manager 이다.
구조
M-HA 는 Manager 와 Node 로 이루어진다. Node 는 MySQL 이 설치된 서버에 모두 설치해줘야 한다. Mater/Slave 구조라면 Node 를 모두 설치해줘야 한다.
Manager 는 이들 Node 를 감시하고 이들 전체를 컨트롤하는 역활을 한다.
M-HA 특징
M-HA 를 AutoFailover 로 사용할만한 이유는 다음과 같다.
Short downtime
MySQL-Replication consistency
Easy Installation
No chagne to existing deployments
M-HA 를 고려할때에 중요한 부분이 짧은 다운타임이다. Master/Slave 구조에서 장애시에 Slave 를 Master 로 빠르게 승격을 시켜주어야 한다. 그래야만 두 서버간에 데이터가 달라지는 데이터 무결성이 깨지지 않게 된다. M-HA 는 비교적 이러한 데이터 무결성을 보장하기 위해서 많은 노력을 기울인 솔루션이라고 보면 된다.
M-HA 구성도
최소한의 환경에서 M-HA 를 구성도는 대략 다음과 같다.
M-HA Node 는 MySQL 이 설치된 서버라면 전부 설치해주어야 한다. M-HA Manager 는 외부서버에 설치해된다.
Node 설치
설치는 M-HA 구글 저장소에 가면 각 배포판별로 바이너리로 배포하고 있어 쉽게 설치가능하다. 여기서는 소스를 가지고 컴파일 설치하도록 하겠다.
Sun Jul1721:26:002016-[warning]Globalconfiguration file/etc/masterha_default.cnfnotfound.Skipping.
Sun Jul1721:26:002016-[info]Reading application defaultconfiguration from/usr/local/etc/mha.cnf..
Sun Jul1721:26:002016-[info]Reading server configuration from/usr/local/etc/mha.cnf..
Sun Jul1721:26:002016-[info]MHA::MasterMonitor version0.57.
Sun Jul1721:26:012016-[error][/usr/local/share/perl5/MHA/ServerManager.pm,ln188]There isno alive server.We can'tdofailover
Sun Jul1721:26:012016-[error][/usr/local/share/perl5/MHA/MasterMonitor.pm,ln427]Error happened on checking configurations.at/usr/local/share/perl5/MHA/MasterMonitor.pmline329.
Sun Jul1721:26:012016-[error][/usr/local/share/perl5/MHA/MasterMonitor.pm,ln525]Error happened on monitoring servers.
Sun Jul1721:26:012016-[info]Got exit code1(Notmaster dead).
MySQL Replication Health isNOTOK!
여기서 버그가 있다. /usr/local/share/perl5/MHA/DBHelper.pm 파일 198 라인에 $host 변수에 문제가 있다.
Mon Jul1801:30:492016-[warning]secondary_check_script isnotdefined.It ishighly recommended setting it tocheck master reachability from two ormore routes.
Mon Jul1801:30:492016-[info]Starting ping health check on192.168.96.32(192.168.96.32:3306)..
Mon Jul1801:30:492016-[debug]Connected on master.
Mon Jul1801:30:492016-[debug]Set shortwait_timeout on master:6seconds
위와같이 로그가 온다면 FailOver 가 정상적으로 된 것이다. 또, 로그 디렉토리 /var/log/masterha 디렉토리에 mha.failover.complete 파일이 생성되어 있을 것이다. 또한, manager 가 죽어 있다. 그러니까 FailOver 가 발생되면 다음과 같이 실행이 된다.
Slave 를 Master 로 승격시킨다.
Manager 에 지정한 로그 디렉토리에 mha.failover.complete 파일을 생성한다.
Manager 가 죽는다.
FailOver 가 발생할때마다 Manager 는 정해진 동작을 수행하고 자동으로 죽게 된다.
승격된 Master 서버에서는 다음을 체크해봐야 한다.
show slave status 명령을 입력했을때 아무것도 나오지 말아야 한다.
show variables like ‘%read%’ 명령어를 입력했을때에 read_only 값이 OFF 여야 한다.
Fedora 배포판의 설정중에 디렉토리 설정 부분을 많이 인용을 했기 때문에 기존의 컴파일 설치한 디렉토리와는 사뭇 다릅니다. 대부분의 소스 컴파일을 설치했을 때에는 대부분 설치할 디렉토리인 PREFIX 만 지정하기 때문에 벤치디렉토리, 서포트디렉토리등이 모드 PREFIX 이하에 놓입니다. 하지만 위 설정을 보시면 Fedora 배포판 호환인 RedHat 디렉토리 구조를 계승하고 있다는 것을 인지하시기 바랍니다.
설치가 끝난 후에는 수동으로 옮겨주어야할 파일들이 존재 합니다. 그래서 설치 후 작업을 다음과 같이 진행 합니다.
MariaDB 는 한 개발자의 노력을 시작된 오픈 소스 프로젝트 입니다. 과거 오픈 소스 데이터베이스의 대명사인 MySQL 을 개발한 개발자 중에 한인 Monty Widenius. 1962년 핀란드 태생으로 1995년 MySQL 데이터베이스를 개발하기 시작해서 그 이듬해에 첫 릴리즈를 하게 됩니다. 그리고 1998년, 3.21 버전부터 www.mysql.com 을 만들어 운영하면서 명실상부한 오픈 소스 데이터베이스로 발을 딛기 시작 합니다.
MySQL은 오픈소스 정책을 가지고 있지만 개발과 판매등을 총괄하는 회사가 있습니다. MySQL AB 라는 회사인데, 개발지원에서부터 판매, 홍보까지 MySQL에 거의 모든것을 관장하던 회사입니다. MySQL이 오픈소스이긴 하지만 라이센스정책이 이중으로 되어있어(GPL, CopyRight) 이러한 라이센스 관련해서 제품의 구성등 전반적인 부분도 이 회사에서 모두 관리합니다.
MySQL이 오픈소스 진영에서 이름을 날리고 있던 2008년에 썬 아킥텍쳐 및 썬 OS로 유명한 ‘Sun microsystems’ 에 85억 달러에 인수 됩니다. 이때에 MySQL을 전부 총괄하던 MySQL AB 회사도 함께 넘어감으로써 모든 지적재산권도 썬으로 넘어가게 됩니다. 그러던 것이 1년도 않된 시점인 2009년 4월 오라클이 썬마이크로시스템즈를 인수함으로써 MySQL AB 의 모든 지적재선권은 다시 오라클로 넘어갑니다.
Oracle. 오픈소스 진영에서는 거의 악날함을 자주 보여줬던 RDBMS 최강의 회사 입니다. 상용시장에서 독보적인 오라클 데이터베이스 를 가지고 있었고 인수전에는 MySQL과 알게 모르게 경쟁하던 데이터베이스 제품을 가진 회사였기 때문에 인수당시부터 오픈소스진영에서는 MySQL에 대한 운명(?)에 대해서 우려하는 목소리가 많았습니다. ‘오라클 스럽게 죽일거다’라는 소리가 자주 들렸지요.
그런데, MySQL AB를 설립했던 Michael “Monty” Widenius(마이클 ‘몬티’ 비드니우스) 라는 사람이 오라클을 뛰쳐 나옵니다. 오픈소스 정의감으로 뛰쳐나왔으면 드라마틱하겠지만 오라클에서 대우가 별로 맘에 않들었다고 하네요. 그러한 그가 나와서 뭘했을 까요? 배운게 도둑질인데, 오라클 회사를 나와서 ‘Monty Program’ 이라는 것을 하게됩니다. 그리고 이 ‘Moty Program’ 에서 GPL 라이센스로 되어있는 MySQL 코드를 Branch 해서 RDBMS를 만들게 되었는데 그것이 바로 ‘MariaDB’ 입니다.
Monty Widenius 는 오라클이 MySQL 을 인수하게되자 오픈 소스 진영에 MySQL 을 구해달라는 호소문을 올리기도 합니다.