안녕하세요! 대담이입니다. 벌써 10월의 마지막이 다가오고 다음주부터는 11월의 시작이 다가오네요 :) 

월동준비는 다들 잘 되고 계신지요?

 

오늘은 MySQL 의 엔진의 스토리지 엔진이라는 특성에 대해 안내드리고, 이중 가장 일반적인 목적에서 많이 사용되고, 높은 퍼포먼스를 보이는 InnoDB 스토리지 엔진에 대해 안내드리겠습니다 :) 

오늘 다룰 내용은 모두 MySQL 공식 레퍼런스 문서 (https://dev.mysql.com/doc/refman/8.0/en/innodb-introduction.html ) 를 참고했음을 미리 안내드리며, 시작해보겠습니다!

  •  

스토리지 엔진이란?

MySQL 아키텍쳐입니다. 출처 : dev.mysql.com

앞서 안내드렸던 MySQL 아키텍쳐에서 보듯이, MySQL은 여러가지의 스토리지 엔진을 채택하여 테이블을 생성할 수 있습니다. 이를 통해 사용자는 목적에 맞는 특화된 스토리지 엔진을 사용할 수도 있는 구조입니다. 아래에 간단한 예시를 들어드리겠습니다.

  • 사용자가 캐시용도의 테이블을 운영하고 싶을 때(데이터가 날아가도 문제 없으나 빨라야함) : MEMORY
  • 로깅 형태의 데이터 저장을 원하는 경우 (트랜잭션은 필요하지 않고 입력속도가 빨라야 함 ) : MyISAM
  • RDBMS의 기본인 트랜잭션을 지원해야하고, 장애에 내구성이 강해야하는 일반적인 경우 : InnoDB
  • 클러스터 구성을 통하여 쓰기 분산등의 이점을 얻고 싶은 경우 : NDBCluster

정도로 앞선 네개 엔진의 특성을 설명 드릴 수 있고, 추가로 사용자가 원하는 스토리지 엔진을 찾아 설치할 수도있습니다. 

이중, 가장 일반적으로, 그리고 재해에 강한 RDBMS의 특성을 가장 잘 반영하는 스토리지 엔진은 InnoDB라고 볼 수 있겠네요. 오늘은 이에 대해 정리를 해드리겠습니다!

 

먼저 InnoDB의 특장점부터 설명드리자면 아래와 같습니다 😁

  • 트랜잭션을 지원합니다(ACID 지원) -> 어찌보면 다른 DBMS에서는 당연히 지원해야하는 것일 수 있겠지만, MySQL의 다른 스토리지 엔진은 성능 등 다른 이유로 트랜잭션을 지원하지 않는 경우가 있습니다. 그러므로 RDBMS의 가장 기본적 특성인 트랜잭션을 지원한다는 것은 아주 매력적인 부분입니다.
  • Row-level 잠금을 지원합니다 -> 잠금을 위하여, Row 단위의 잠금을 사용하므로 DML의 동시성을 늘릴 수 있습니다. 
  • Primary Key 위주의 정렬로 Primary Key 기준의 쿼리 수행시 가장 최적화된 쿼리를 수행 가능합니다. 이에 대해서는 차후 클러스터드 인덱스 항목을 통하여 더 자세히 구조에 대해 다뤄보겠습니다. 
  • 데이터 정합성을 보장하기 위하여 외래키 기능을 지원합니다.
  • 기본적으로 읽기시, 잠금 없는 일관된 읽기를 지원합니다. MVCC, 혹은 버전 컨트롤이라 불리는 이 내용에 대해서는 차후 더 자세히 다루도록 하겠습니다.

오늘은 여기서, InnoDB의 메모리 구조에 대해 안내드리려고 합니다.

 

InnoDB Buffer pool

먼저 InnoDB의 메모리 구조를 안내드리기 위해선, 일반적으로 MySQL 메모리의 가장 큰 부분을 차지하는 버퍼풀을 빼놓고 얘기할 수 없습니다. 일반적인 목적으로 사용하는 MySQL의 경우, 만약 다른 어플리케이션이 수행되지 않는 DB 전용 서버의 경우, 버퍼 풀의 사이즈를 전체 메모리 용량의 3/4 까지도 잡아서 사용합니다.

여기에는 사용자가 접근한 테이블과 인덱스 데이터가 저장됩니다. 그리고 앞선 SELECT 수행절차에서 말씀드렸던(https://daedamee.tistory.com/entry/MySQL-Internal-%EC%82%B4%ED%8E%B4%EB%B3%B4%EA%B8%B0-SELECT-%EC%88%98%ED%96%89%EA%B3%BC%EC%A0%95?category=727646) 메모리에 항상 올리고 시작하는 개념이 이 버퍼풀이라고 생각하시면 더 편하시겠죠? 😃

메모리 영역이 디스크보다 크다면 모든 데이터를 항상 메모리에 들고있을 수있어 굉장히 쾌적하게 이용할 수 있겠지만, 우리모두가 알고있듯 램은 비싸고 디스크는 저렴합니다. 그러므로 제한된 메모리를 효율적으로 사용하기 위해 InnoDB에서는 Least recently used (LRU) 알고리즘을 사용합니다. 자주 접근하는 데이터는 밀리지 않도록 앞으로 당기고, 자주 사용되지 않는 데이터는 메모리에서 제거하는(eviction이라고 부릅니다) 우선순위에 두는 방식으로 운영됩니다.

 

Innodb 버퍼풀 LRU 리스트 설명 페이지입니다.

기본적으로 버퍼풀의 3/8은 old sublist로 분류되며(밀려날 수 있는 페이지들), 나머지는 new list로, 그리고 그 사이를 midpoint로 부릅니다. old list의 페이지를 읽게 된다면 이는 다시 new list로 바뀌게 되며, 사용자의 요청으로 읽히게 되도 이 페이지는 new list로 가게 됩니다. 데이터베이스가 운영될때, 버퍼풀의 페이지는 "나이" 에 의해 움직이진 않습니다. 

 

 

 

그리고 이에 대한 모니터링은 SHOW ENGINE INNODB STATUS; 명령을 통해 가능한데요, 아래 코드에서 간단히 설명드리겠습니다.

 

mysql> SHOW ENGINE INNODB STATUS\G
*************************** 1. row ***************************
.....
----------------------
BUFFER POOL AND MEMORY -- 버퍼풀 메모리 영역의 설명입니다. 사용하지 않는 곳이라 아주 깨끗하네요 :) 
----------------------
Total large memory allocated 0 -- 버퍼풀에 얼마나 많은 메모리가 할당되었는지 나타냅니다.
Dictionary memory allocated 366605 -- InnoDB 데이터 딕셔너리가 얼마나 할당되어있는지 나타냅니다.
Buffer pool size   8192 -- 버퍼풀에 할당된 페이지의 사이즈입니다.
Free buffers       7061 -- 버퍼풀에 할단된 페이지 중, free 한 사이즈입니다.
Database pages     1127 -- 버퍼풀 LRU 리스트의 페이지의 사이즈입니다. 
Old database pages 436  -- LRU Old 서브리스트에 있는 페이지의 사이즈입니다.
Modified db pages  0    -- 버퍼풀에서 변경된 페이지의 현재 숫자입니다.
Pending reads      0    -- 버퍼풀에서 읽기를 대기하는 페이지의 숫자입니다.
Pending writes: LRU 0, flush list 0, single page 0 -- 쓰기를 대기하는 페이지로, LRU의 경우 더티페이지를, flush의 경우 체크보인팅을, single의 경우 독립 페이지를 의미합니다.
Pages made young 0, not young 0 -- LRU리스트에서 young으로 만들어지는 페이지와 이게 아닌 페이지입니다.
0.00 youngs/s, 0.00 non-youngs/s
Pages read 985, created 142, written 158 -- 버퍼풀에서 읽히고/만들어지고/쓰인 페이지 숫자입니다.
0.00 reads/s, 0.00 creates/s, 0.00 writes/s
No buffer pool page gets since the last printout
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
LRU len: 1127, unzip_LRU len: 0
I/O sum[0]:cur[0], unzip sum[0]:cur[0]

----------------------------
END OF INNODB MONITOR OUTPUT
============================

1 row in set (0.00 sec)

mysql>

 

 

이상, 버퍼풀에 대해서 간단히 구조에 대해 공식 문서 및 간단한 명령을 통해 알아보았습니다! 

MySQL에서 메모리의 용량이 데이터베이스에 어떤 영향을 미치는지, 그리고 자주 액세스하는 데이터가 왜 빠르게 리턴하는지에 대해 알 수 있는 시간이 되었네요!

 

긴 글 읽어주셔서 감사드리며, 다음 문서를 통해 메모리 구조에 대해 남은 Change buffer, Adaptive Hash Index, Log Buffer에 대해서도 정리하는 시간을 가져보겠습니다.

 

그럼 오늘도 모두 즐거운 하루 되세요!

+ Recent posts