서론
SSAFY를 하며 CS 스터디를 진행하고 있다. CS 스터디에서 OS 파트를 진행할 때는 블로그 포스팅을 하지 못했지만, 이번 DB 파트에 대해서는 포스팅을 해보고자 한다.
포스팅의 내용은 모두 Real MySQL 8.0 책을 기반으로 작성할 것이며, 추가로 참고한 블로그나 웹 페이지가 존재한다면 참고 링크를 남겨놓을 예정이다. AI(ChatGPT, Gemini)를 통해 이해한 내용을 포함할 수 있다.
Real MySQL 8.0 (1권) | 백은빈 - 교보문고
Real MySQL 8.0 (1권) | MySQL 서버를 활용하는 프로젝트에 꼭 필요한 경험과 지식을 담았습니다!《Real MySQL 8.0》은 《Real MySQL》을 정제해서 꼭 필요한 내용으로 압축하고, MySQL 8.0의 GTID와 InnoDB 클러스
product.kyobobook.co.kr
아키텍처
MySQL 서버 구성
- MySQL 엔진
- 스토리지 엔진
- InnoDB 스토리지 엔진
- MyISAM 스토리지 엔진
전체 구조

MySQL 엔진
- 커넥션 핸들러: 클라이언트로부터의 접속 및 쿼리 요청을 처리
- SQL 파서 및 전처리기, 쿼리의 최적화된 실행을 위한 옵티마이저
스토리지 엔진
- 요청된 SQL 문장을 분석하거나 최적화 등의 처리를 수행
- 실제 데이터를 디스크 스토리지에 저장하거나 읽어오는 부분을 전담
- 테이블이 사용할 스토리지 엔진을 지정하면 해당 테이블의 모든 작업은 정의한 스토리지 엔진에서 처리
MySQL 서버에서 MySQL 엔진은 1개만 존재한다. 하지만 스토리지 엔진은 여러 개를 동시에 사용할 수 있다.
핸들러 API
- 핸들러 요청: MySQL 엔진의 쿼리 실행기에서 데이터를 쓰거나 읽어야 할 때, 각 스토리지 엔진에 쓰기 또는 읽기 요청
- 이때 사용하는 API를 의미
커넥션 핸들러는 클라이언트의 접속 및 쿼리 요청을 처리하는 최상위 레이어이고,
핸들러는 실제 데이터에 접근하기 위해 스토리지 엔진에게 명령을 전달할 때 사용한다. MySQL 엔진이 스토리지 엔진에 접근하는 인터페이스 역할이다.
MySQL 스레딩 구조

MySQL 서버는 스레드 기반으로 작동
Foreground와 Background로 구분
Foreground (클라이언트 스레드)
- 최소한 MySQL 서버에 접속된 클라이언트의 수만큼 존재한다.
- 각 클라이언트 사용자가 요청하는 쿼리 문장을 처리한다.
- thread_cache_size 시스템 변수를 통해 스레드 캐시에 유지할 수 잇는 최대 스레드 개수를 설정할 수 있다. 이를 기반으로 이미 스레드 캐시에 일정 개수 이상의 대기 중인 스레드가 있으면 캐시에 넣지 않고 종료시킨다.
- 데이터를 MySQL 데이터 버퍼나 캐시로부터 가져온다. 없는 경우에는 디스크의 데이터나 인덱스 파일로부터 데이터를 읽어온다.
- InnoDB는 데이터 버퍼나 캐시까지만 Foreground 스레드가 처리하며, 디스크까지 기록하는 작업은 Background 스레드가 처리한다.
- MyISAM은 디스크 쓰기 작업까지 Foreground 스레드가 처리한다.
Backgound
- InnoDB는 여러 작업을 Backgound로 처리하는데, 가장 중요한 것은 로그 스레드(Log thread)와 버퍼의 데이터를 디스크에 쓰는 작업을 하는 쓰기 스레드(Write thread)이다.
- 데이터를 읽는 작업은 Foreground 스레드에서 처리되기 때문에 읽기 스레드는 많이 설정할 필요가 없다.
- 즉, Foreground는 접속한 클라이언트 수에 따라 개수가 결정된다.
- 사용자는 최대 접속 수 제한을 설정할 수 있지만, Foreground 스레드의 개수를 설정하지는 않는다.
- 쓰기 스레드는 많은 작업을 Backgound로 처리하기 때문에 디스크를 최적으로 사용할 수 있을 만큼 충분히 설정해야 한다.
데이터 쓰기 작업은 지연되어 처리 될 수 있지만, 데이터의 읽기 작업은 절대 지연될 수 없다.
- InnoDB에서는 쓰기 작업을 버퍼링해서 일괄 처리하는 기능이 탑재되어 있다.
Foreground 스레드는 데이터를 디스크에 바로 쓰지 않고, 버퍼 풀에만 기록하고 클라이언트에게 즉시 COMMIT 응답을 준다.
데이터 파일에 쓰기 전에 Redo Log를 먼저 기록해 데이터의 영속성(Durability)을 보장한다. Redo Log가 있기 때문에 데이터 파일에 쓰는 작업을 지연시켜도 안전하다.
→ Foreground 스레드는 쓰기 작업을 디스크 I/O로부터 분리할 수 있으며, 쓰기 작업을 지연 처리해 성능을 높인다. - MyISAM은 쓰기 버퍼링 기능을 사용할 수 없다.
Redo Log와 같은 복구 메커니즘이 없기 때문에, 클라이언트가 쓰기 요청을 하면 해당 Foreground 스레드가 즉시 데이터를 디스크 파일에 기록해야 한다. 디스크 I/O가 완료될 때까지 클라이언트는 응답을 받을 수 없고, Foreground는 블로킹(Blocking)상태가 된다.
→ Foreground 스레드가 디스크 쓰기 I/O를 직접 처리하며, 쓰기 작업을 지연시킬 수 없다.
메모리 할당 및 사용 구조

글로벌 메모리 영역
- MySQL 서버가 시작되면서 운영체제로부터 할당
- 하나의 메모리 공간만 할당된다. 클라이언트 스레드의 수와 무관하다.
- 모든 스레드에 의해 공유된다.
로컬 메모리 영역 (세션 메모리 영역)
- Foreground 스레드가 쿼리를 처리하는 데 사용하는 메모리 영역
- 대표적으로 커넥션 버퍼와 정렬(소트) 버퍼 등이 있다.
- 각 클라이언트 스레드(Foreground 스레드)별로 독립적으로 할당되며 절대 공유되어 사용되지 않는다.
- 커넥션이 열리 있는 동안 계속 할당된 상태로 남아 있는 공간 → 커넥션 버퍼, 결과 버퍼
- 쿼리를 실행하는 순간에만 할당했다가 다시 해제하는 공간 → 소트 버퍼, 조인 버퍼
플러그인 스토리지 엔진 모델
스토리지 엔진 뿐만 아니라 파서를 개발해서 사용할 수 있으며, Native Authentication, Caching SHA-2 Authentication 등도 플러그인으로 구현되어 제공된다.

MySQL 엔진에서 대부분의 작업이 처리도며, 데이터 읽기/쓰기 작업만 스토리지 엔진에서 처리한다.
다른 스토리지 엔진을 사용하는 테이블에 대해 쿼리를 실행하더라도 MySQL의 처리 내용은 대부분 동일하며, 데이터 읽기/쓰기 영역의 처리만 차이가 있을 뿐이다.
여기서 중요한 내용은 '하나의 쿼리 작업은 여러 하위 작업으로 나뉘는데, 각 하위 작업이 MySQL 엔진 영역에서 처리되는지 아니면 스토리지 엔진 영역에서 처리되는지 구분할 줄 알아야 한다'는 점이다.
컴포넌트
기존의 플러그인 아키텍처를 대체하기 위함
- 플러그인은 오직 MySQL 서버와 인터페이스할 수 있고, 플러그인끼리는 통신할 수 없음
- 플러그인은 MySQL 서버의 변수나 함수를 직접 호출하기 때문에 안전하지 않음 (캡슐화 X)
- 플러그인은 상호 의존 관계를 설정할 수 없어서 초기화가 어려움
쿼리 실행 구조

- 쿼리 파서: 사용자 요청으로 들어온 쿼리 문장을 토큰으로 분리해 트리 형태의 구조로 만들어 내는 작업
- 전처리기: 파서 과정에서 만들어진 파서 트리를 기반으로 쿼리 문장에 구조적인 문제점이 있는지 확인
- 옵티마이저: 사용자의 요청으로 들어온 쿼리 문장을 저렴한 비용으로 가장 빠르게 처리할지를 결정하는 역할
- 실행 엔진: 만들어진 게획대로 각 핸들러에게 요청해서 받은 결과를 또 다른 핸들러 요청의 입력으로 연결하는 역할
스레드 풀 (Percona Server 기반)
목적: 사용자의 요청을 처리하는 스레드 개수를 줄여서 동시 처리되는 요청이 많다하더라도 MySQL 서버의 CPU가 제한된 개수의 스레드 처리에만 집중할 수 있게 해서 서버의 자원 소모를 줄이는 것
MySQL 서버가 처리해야 할 요청이 생기면 스레드 풀로 처리를 이관하는데, 이미 스레드 풀이 처리 중인 작업이 있는 경우에는 thread_pool_oversubscribe 시스템 변수에 설정된 개수만큼 추가로 더 받아 들여서 처리한다.
스레드 그룹의 모든 스레그가 일을 처리하고 있다면 스레드 풀은 해당 스레드 그룹에 새로운 작업 스레드를 추가할지, 아니면 기존 작업 스레드가 처리를 완료할 때까지 기다릴지 여부를 판단해야 한다.
- 타이머 스레드는 스레드 그룹의 상태를 주기적으로 체크
- 작업 스레드가 지금 처리 중인 작업을 정의된 시간(thread_pool_stall_limit) 내에 끝내지 못하면 새로운 스레드를 생성해서 스레드 그룹에 추가
- 이때 전체 스레드의 개수는 thread_pool_max_threads 시스템 변수에 설정된 개수를 넘을 수 없음
선순위 큐와 후순위 큐를 사용해 특정 트랜잭션이나 쿼리를 우선적으로 처리할 수 있는 기능도 있다.
트랜잭션 지원 메타데이터
테이블의 구조 정보나 스토어드 프로그램의 코드 관련 정보 등 MySQL 서버가 작동하는 데 필요한 테이블들(시스템 테이블)은 모두 InnoDB의 테이블에 저장한다.
MyISAM과 같은 스토리지 엔진의 메타 정보는 여전히 저장할 공간이 필요하다.
MySQL 서버는 InnoDB 스토리지 엔진 이외의 스토리지 엔진을 사용하는 테이블들을 위해 SDI(Serialized Dictionary Information) 파일을 사용한다.
내용이 너무 길어져 InnoDB와 MyISAM에 대해서는 따로 포스팅하도록 하겠다.
이후 진행 예정
- MySQL 아키텍처2_InnoDB 스토리지 엔진
- MySQL 아키텍처3_MyISAM 스토리지 엔진
'Study > CS' 카테고리의 다른 글
| [CS]MySQL 아키텍처2_InnoDB 스토리지 엔진 (7) | 2025.12.09 |
|---|---|
| [CS]Network (1) | 2024.06.20 |
| [CS]OS(Operating System) (1) | 2024.06.13 |
| [CS]Computer Architecture - 하드웨어, 시스템 버스, CPU, 캐시 메모리 (3) | 2024.05.29 |