2026. 3. 26. 00:31ㆍ개발
이 글은 백은비, 이성욱 님의 'Real MySQL 8.0'을 참고하여 공부한 내용입니다.
이번에 좋은 기회로 인턴십에 합격하여 서버 실무를 경험할 수 있게 되었습니다. 좋은 일이지만 스스로의 역량이 얼마나 부족한가 알게 되었는데요. 특히 DB에 대한 이해가 너무 없다고 절절하게 느껴졌습니다. 그래서 이제부터라도 DB에 대해 공부해 보려고 합니다.

서버 아키텍처
MySQL 서버는 크게 MySQL 엔진과 스토리지 엔진으로 나누어집니다. 두 엔진의 작업 내용은 다르지만 핸들러 API를 호출하여
상호작용하며 클라이언트 요청을 처리합니다.
MySQL 엔진
MySQL 엔진은 클라이언트의 프로그래밍 API로 부터 요청되는 접속 및 쿼리 요청을 처리하는 커넥션 핸들러와 인터페이스, 파서, 옵티마이저, 캐시버퍼로 구성되어 있습니다. 그래서 클라이언트의 요청을 읽어 SQL 문장으로 파싱, 실행계획을 세워 최적화를 하는 등의 작업을 수행합니다.
스토리지 엔진
위 MySQL 엔진에서 클라이언트 요청을 해석하고 최적화했다면 스토리지 엔진에서는 실제 데이터를 디스크 스토리지에 저장하거나 읽어오는 작업을 수행합니다. 또한 스토리지 엔진은 MySQL 서버 내부에서 여러 개의 엔진을 사용할 수 있습니다. 책에서는 주로 스토리지 엔진을 InnoDB와 MyISAM을 설명합니다.
스레딩 구조
MySQL의 병렬 작업처리는 스레드 기반으로 되어 있습니다. 그리고 스레드는 담당하는 작업을 기준으로 포그라운드 스레드, 백그라운드 스레드로 구분합니다.
포그라운드 스레드
클라이언트 스레드라고도 부르며 MySQL 접속된 클라이언트의 수 만큼 스레드가 존재합니다. 주 작업은 클라이언트가 요청하는 쿼리 문장을 처리하고 결과를 클라이언트에게 응답합니다. 클라이언트가 작업을 마치고 커넥션을 종료하면 해당 포그라운드 스레드는 다시 스레드 캐시로 돌아갑니다. 만약 스레드 캐시에 thread_cache_size 만큼의 스레드가 존재한다면 해당 스레드를 종료합니다.
스레드 캐시는 스레드 풀과 스레드를 관리하는 목적은 공통되지만 스레드 캐시는 존재하는 모든 스레드를 사용 후 클라이언트 요청이 추가로 있다면 스레드를 생성하여 해당 클라이언트의 요청을 처리합니다. 즉 단순하게 스레드의 생성/종료에 소모되는 오버헤드를 줄이기 위함입니다.
또한 포그라운드 스레드는 요청을 처리하는 테이블의 스토리지 엔진에 따라 작업 범위가 달라질 수 있습니다. MyISAM은 데이터를 데이터 버퍼나 캐시로부터 읽어 작업을 처리합니다. 심지어 MyISAM은 디스크 쓰기 작업까지 포그라운드 스레드에서 처리하지만 InnoDB는 데이터 버퍼나 캐시까지만 처리하며 나머지 디스크 쓰기 작업은 백그라운드 스레드에서 처리하게 됩니다.
백그라운드 스레드
MyISAM의 경우 백그라운드 스레드에 해당사항이 없지만 InnoDB의 경우 여러 가지 작업을 백그라운 스레드로 나눠서 처리하게 됩니다. 아래는 백그라운드 스레드가 처리하는 작업들입니다.
- 인서트 버퍼를 병합
- 로그를 디스크로 기록
- InnoDB 버퍼 풀의 데이터를 디스크에 기록
- 데이터를 버퍼로 읽기
- 잠금이나 데드락 모니터링
백그라운드 스레드의 사용으로 InnoDB는 읽기 작업의 지연을 없에는 쓰기 버퍼링 기능을 사용할 수 있습니다. 하지만 MyISAM은 포그라운드 스레드가 쓰기 작업까지 처리하도록 설계되어 일반적인 쿼리는 쓰기 버퍼링 기능을 사용할 수 없습니다.
메모리 할당 및 사용 구조
MySQL에서 사용되는 메모리 공간은 크게 글로벌 메모리 영역과 로컬 메모리 영역으로 구분됩니다. 서버 내 스레드들이 공유해서 사용하는 메모리 여부에 따라 구분됩니다.
글로벌 메모리 영역
MySQL 서버가 실행할 때 운영체제로부터 할당되며 필요에 따라 2개 이상의 공간을 할당받을 수도 있습니다. 글로벌 메모리 영역은 개수에 상관없이 모든 스레드에 의해 공유됩니다. 아래는 대표적으로 글로벌 메모리 영역에 해당하는 메모리 공간 목록입니다.
- 테이블 캐시
- InnoDB 버퍼 풀
- InnoDB 어댑티브 해시 인덱스
- InnoDB 리두 로그 버퍼
로컬 메모리 영역
세션 메모리 영역, 클라이언트 메모리 영역 이라고도 불리며 포그라운드 스레드가 쿼리를 처리하는데 사용하는 메모리 영역입니다. 로컬 메모리 영역은 해당 작업을 처리하는 스레드만 접근할 수 있으며 쿼리에 따라 필요할 때만 공간이 할당됩니다. 아래는 대표적으로 로컬 메모리 영역에 해당하는 메모리 공간 목록입니다.
- 정렬 버퍼
- 조인 버퍼
- 바이너리 로그 캐시
- 네트워크 버퍼
플러그인 스토리지 엔진 모델
MySQL의 가장 큰 특징 중 하나로 필요에 따라 플러그인 모델을 사용해서 유연성을 높이고 직접 엔진을 개발하여 확장성과 최적화를 높일 수 있습니다. 즉 필요에 따라 MySQL 서버에 추가적인 기능을 제공하는 외부 모듈을 이식할 수 있는 아키텍처입니다.
이를 가능하게 해주는 것이 Handler API를 호출하여 표준 인터페이스로 작업을 처리하는 작동방식입니다. MySQL 엔진과 스토리지 엔진이 달라져도 표준 인터페이스로 명령을 호출하기 때문에 각 스토리지 엔진의 내부 구현 방식에 따라 명령을 처리합니다.
중요한 것은 하나의 쿼리 작업은 여러 하위 작업으로 나뉘는데 각 하위 작업이 MySQL 서버 영역에서 처리되는지 아니면 스토리지 엔진 영역에서 처리되는지 구분할 줄 알아야 합니다.
컴포넌트
MySQL 8.0부터 플러그인의 단점을 보완하기 위해 컴포넌트 아키텍처로 대체되었습니다. 플러그인의 단점은 아래와 같습니다.
- 플러그인은 오직 MySQL 서버와 인터페이스를 할 수 있고, 플러그인끼리 통신할 수 없음
- 플러그인은 MySQL 서버의 변수나 함수를 직접 호출하기 때문에 안전하지 않음(캡슐화가 안 됨)
- 플러그인은 상호 의존 관계를 설정할 수 없어서 초기화가 어려움