'innodb'에 해당되는 글 2건

  1. 2016.08.22 innodb_flush_method, O_DIRECT에 대한 오해! 1
  2. 2016.06.08 InnoDB Buffer Pool 덤프 & 로드

innodb_flush_method, O_DIRECT에 대한 오해!



innodb_flush_method 설정은 InnoDB가 데이터 파일을 어떤 방식으로 읽고 쓰기를 할것인지


선택할수 있게 해준다.


그중 O_DIRECT 설정값을 흔히 사용하는데 이유를 물어보면 IO 성능향상을 위해서라고 한다.


웹상의 많은 글에도 IO 성능향상을 위해 O_DIRECT를 쓰라는 글이 많아 보이는데 물론 완전히 틀린말은 아니지만


좀 더 정확히 알고 쓰자라는 취지에서 글을 남겨본다.




O_DIRECT


거의 모든 UNIX&Linux 시스템에서는 모든 데이터 읽기/쓰기에 OS 캐시를 사용한다.


이러한 캐시기반에서는 어플리케이션이 데이터를 읽을때 가장 먼저 OS캐시에 원하는 데이터가 있는지 찾아보고


원하는 데이터가 캐시에 있다면 그대로 가져다 쓰고 만약 캐시에 원하는 데이터가 없다면 디스크에서 데이터를 찾아다가


캐시에 먼저 복사한 다음에 어플리케이션에 데이터를 돌려준다. 


O_DIRECT 옵션은 바로 이 OS캐시를 MySQL/MariaDB 에서 사용하지 않겠다라는 선언이다.



[ fdatasync ]

DB -> OS캐시 -> DataFile 



[ O_DIRECT ]

DB -> DataFile



OS캐시를 거치는 과정이 없어졌으므로 IO 과정이 단순화 되어 빨라질꺼라 착각할수 있지만 실제로는 전혀아니다.


캐시=메모리 라는 점을 다시 생각해보면 OS캐시는 느려터진 디스크와 DB간의 완충작용을 해주기 때문에 


O_DIRECT를 쓰게되면 버퍼풀에서 읽어오는 읽기성능은 차치하더라도 쓰기성능은 오히려 더 나빠질수 밖에 없다.  


그렇다면 O_DIRECT를 쓰는 진짜 이유는 무엇일까?




이유 


IO 성능 저하를 감안하면까지 O_DIRECT를 사용하는 가장 큰 이유는 더블버퍼링을 막아 메모리를 효율적으로 쓰기 위함이다.


(더블버퍼링을 더블라이트버퍼(Double Write Buffer)와 헷갈리면 안된다. 더플라이트버퍼는 데이터의 안전성을 위해


디스크상에 중복된 데이터를 이중으로 저장하는 것이고 여기서 말한 더블버퍼링은 메모리상에서의 중복 저장을 의미한다.)


InnoDB는 이미 버퍼풀(Buffer Pool)이라는 훨씬 고도화된 메모리 관리 영역을 가지고 있기 때문에 동일한 데이터를


버퍼풀과 OS캐시에 중복으로 저장해 메모리를 낭비할 필요가 없다.


그리고 두번째 이유는 OS캐시에 대한 무한한 불신(ㅋㅋㅋㅋ) 때문이 아닐까? 사실 OS캐시가 우리가 생각하는것 만큼


똑똑하게 움직여주진 않는다. OS캐시는 되도록 많은 데이터를 캐시하려고 하기 때문에 어느순간 버퍼풀의 데이터가 


스왑으로 빠져버리는 경우도 허다하기 때문이다. 물론 vm.swappiness 를 수정하거나 innodb_buffer_pool_populate 를 


설정할 수 도 있겠으나 해당서버에 DB이외에 다른 어플리케이션이 있을수도 있고 innodb_buffer_pool_populate 는 


아직 MariaDB에서만 지원되며 다른 예외사항이 발생할수 있기 때문에 O_DIRECT를 쓰는게 DB가 OS캐시를 사용할수 없게 


강제할수 있는 가장 쉽고 빠른 방법이 될 수도 있다.




조건


O_DIRECT를 썻다면 쓰기 성능이 나빠지게 되는데 이를 보완해줄수 있는게 RAID 컨트롤러의 캐시다.


OS와는 전혀 별개의 캐시를 IO에 사용하기 때문에 스와핑이나 기타 변수가 발생할 염려없이 쓰기 성능을 


보장해주므로 이런 캐시를 내장한 컨트롤러를 쓴다면 O_DIRECT를 검토하도록 하자. 물론 BBU까지 있다면 금상첨화다!




ETC


O_DIRECT를 쓰더라도 데이터파일에 대해서만 OS캐시를 안쓸뿐이다. 만약 Redo로그에서도 OS캐시를 쓰지 않겠다면


ALL_O_DIRECT를 사용하면 된다.

InnoDB Buffer Pool 덤프 & 로드



InnoDB는 자주 사용하는 데이터를 버퍼풀에 모두 올려놓고 사용하는데 서버나 데몬이 


재가동될시에는 모든 캐시를 잃게 된다. 그래서 재가동 직후에는 디스크에서 모든 데이터를 


다시 읽어와야 되기 때문에 과부하가 걸리기 쉽다. 


물론 임의로 테이블과 인덱스를 풀스캔하면서 워밍업을 해줄순 있겠지만 사용량이나 빈도에 따라


잘~ 정리되어있던 예전 버퍼풀만 못할것이다. 



그래서 서버를 내리기 직전의 현재 버퍼풀을 덤프해 저장해두고 서버 재기동시 덤프를 복구해


재기동으로 인한 과부하를 막을수 있는 방법을 알아보도록 하자.



설정변수


MariaDB [(none)]> show variables like  'innodb_buffer_pool%';

+-------------------------------------+----------------+

| Variable_name                       | Value          |

+-------------------------------------+----------------+

| innodb_buffer_pool_dump_at_shutdown | OFF            |

| innodb_buffer_pool_dump_now         | OFF            |

| innodb_buffer_pool_dump_pct         | 100            |

| innodb_buffer_pool_filename         | ib_buffer_pool |

| innodb_buffer_pool_instances        | 8              |

| innodb_buffer_pool_load_abort       | OFF            |

| innodb_buffer_pool_load_at_startup  | OFF            |

| innodb_buffer_pool_load_now         | OFF            |

| innodb_buffer_pool_populate         | OFF            |

| innodb_buffer_pool_size             | 8589934592     |

+-------------------------------------+----------------+

10 rows in set (0.00 sec)


Mariadb 10.1 기준으로 innodb_buffer_pool 을 검색해보면 총 10개가 나오는데


버퍼풀 덤프&로드 작업에 필요한것도 있고 아닌것도 있지만.... 일단 나왔으니 다 정리해보자.


- innodb_buffer_pool_dump_at_shutdown

이 옵션이 ON으로 설정되어 있으면 서버가 정상종료시 자동으로 버퍼풀을 덤프한다.


- innodb_buffer_pool_dump_now

이 옵션의 값은 항상 OFF 이고 ON 으로 바꾸게 되면 그 즉시 버퍼풀을 덤프한다. 덤프가 끝나면 자동으로 OFF로 바뀐다.


- innodb_buffer_pool_dump_pct

버퍼풀의 얼마만큼을 덤프할껀지에 대한 퍼센트 값이다. 버전에 따라 기본값이 다르다.


- innodb_buffer_pool_filename

자동이든 수동이든 덤프된 파일명이다. 경로는 기본적으로 data 디렉토리다.


- innodb_buffer_pool_instances

버퍼풀을 운영할 인스턴스를 몇개나 띄우건지 지정해준다.


- innodb_buffer_pool_load_abort

버퍼풀을 로드하고 있을때 이 값을 ON으로 바꿔주면 로드가 취소된다.


- innodb_buffer_pool_load_at_startup

이 옵션이 ON으로 설정되어 있으면 서버 구동시 자동으로 덤프된 버퍼풀을 로드한다.


- innodb_buffer_pool_load_now

이 옵션도 항상 OFF 이고 이 값을 ON으로 바꾸면 그 즉시 덤프된 버퍼풀을 로드한다.


- innodb_buffer_pool_populate

이 값이 ON이면 서버 구동시 지정된 버퍼풀 사이즈 만큼의 메모리를 모두 할당한다.


- innodb_buffer_pool_size

MySQL, MariaDB에서 가장 중요한 옵션. 인덱스와 데이터에 대한 캐시사이즈 값이다.



위 설정중에 innodb_buffer_pool_instances, innodb_buffer_pool_populate, innodb_buffer_pool_size


3가지는 덤프&로드와는 무관한 옵션들이다.



실행 조건


>= MySQL5.6, >= MariaDB10.0



버퍼풀 덤프하기


MariaDB [(none)]> set global innodb_buffer_pool_dump_now=ON;

Query OK, 0 rows affected (0.00 sec)


MariaDB [(none)]> exit

Bye

[root@localhost ~]# ls -alh /app/mariadb/data/

합계 2.2G

drwxrwxr-x  5 mysql mysql  4.0K 2016-06-08 15:35 .

drwxr-xr-x 12 root  root   4.0K 2016-05-02 17:57 ..

-rw-rw----  1 mysql mysql   16K 2016-05-11 16:49 aria_log.00000001

-rw-rw----  1 mysql mysql    52 2016-05-11 16:49 aria_log_control

-rw-r-----  1 mysql root    76K 2016-06-08 15:35 error-log.err

-rw-rw----  1 mysql mysql  9.8K 2016-06-08 15:35 ib_buffer_pool

-rw-rw----  1 mysql mysql  128M 2016-06-08 15:34 ib_logfile0

-rw-rw----  1 mysql mysql  128M 2016-04-29 14:53 ib_logfile1

-rw-rw----  1 mysql mysql  128M 2016-04-29 14:54 ib_logfile2

-rw-rw----  1 mysql mysql  128M 2016-04-29 14:54 ib_logfile3

-rw-rw----  1 mysql mysql 1000M 2016-06-08 15:33 ibdata1

-rw-rw----  1 mysql mysql     0 2016-04-20 19:41 multi-master.info

drwx------  2 mysql mysql  4.0K 2016-04-20 19:41 mysql

drwx------  2 mysql mysql  4.0K 2016-04-20 19:41 performance_schema

-rw-rw-r--  1 mysql mysql  9.7K 2016-05-12 11:42 slow.log

-rw-rw----  1 mysql mysql   24K 2016-05-11 16:49 tc.log



이건 실서버가 아니라 덤프파일이 9.8K 밖에 안되지만 실서버라 해도 용량이 그렇게 크지 않다.


버퍼풀 덤프는 메모리에 있는 모든 내용을 파일로 쓰는게 아니라 버퍼풀에 캐싱된 페이지들의 


id 와 no 값만을 저장하기 때문이다. 그래서 버퍼풀이 몇백기가라 할지라도 덤프파일은 몇백메가면 충분하다.



버퍼풀 로드하기


MariaDB [(none)]> set global innodb_buffer_pool_load_now=ON;

Query OK, 0 rows affected (0.00 sec)


MariaDB [(none)]> show status like 'innodb_buffer_pool_load_status';

+--------------------------------+--------------------------------------------------+

| Variable_name                  | Value                                            |

+--------------------------------+--------------------------------------------------+

| Innodb_buffer_pool_load_status | Buffer pool(s) load completed at 160608 15:45:15 |

+--------------------------------+--------------------------------------------------+

1 row in set (0.01 sec)



innodb_buffer_pool_load_status 상태값으로 로드 현황을 볼 수 있다.


예제로 사용한 덤프파일이 작아서 너무 금방끝나는 바람에 completed 화면만 볼 수 있는데


로드중일때는 Loaded 4444/9999 pages 와 같이 진행상태를 확인할수 있다.





to Top