본문 바로가기
독서기록장

10. Real MySQL 4장 아키텍처

by pon9 2025. 4. 11.

Mysql 아키텍처

Mysql 서버 구조:

쿼리 파싱, 최적화, 실행을 담당하는 Mysql 엔진과

실제 데이터를 디스크에 저장하고, 조회하는 스토리지 엔진으로 나눔.

 

Mysql 엔진은 커넥션 핸들러, SQL 파서, 전처리기, 옵티마이저 등으로 이루어짐

 

스토리지 엔진은 대표적으로 

InnoDB: 트랜잭션, 외래 키, 버퍼 풀 등을 지원

MyISAM: 빠른 읽기, 단순한 구조, 트랜잭션 없음

SHOW ENGINES; 하면 스토리지 엔진 확인 가능함

이렇게

 

스레딩 모델

Foreground 스레드:

클라이언트 요청을 처리(커넥션 연결 담당)하고, 쿼리 처리 후 스레드 캐시에 반환되어 재사용됨

이미 스레드 캐시에 일정 개수 이상의 대기 중인 스레드가 있으면, 스레드를 종료시켜서 일정 개수의 스레드만 캐시에 존재하게 함

데이터를 Mysql의 데이터 버퍼나 캐시에서 가져오며, 버퍼나 캐시에 없는 경우 직접 디스크에 접근하게 됨(InnoDB는 디스크에서부터는 백그라운드 스레드 담당)

 

Background 스레드:

디스크 I/O, 버퍼 풀 플러시, 로그 기록 등 내부 작업을 처리함

읽기/쓰기 병렬설 향상을 위해 여러 개의 스레드로 구성됨

InnoDB의 경우, 쓰기작업은 버퍼링될 수 있지만 읽기 작업은 버퍼링을 지원하지 않음

 

메모리 구조

글로벌 메모리:

모든 스레드가 공유함(테이블 캐시, InnoDB 버퍼 풀, 리두 로그 버퍼)

 

로컬 메모리:

쿼리 실행 중 세션 단위로 일시적으로 사용됨(정렬 버퍼, 조인 버퍼, 바이너리 로그 캐시)

각 스레드별로 독립적으로 할당되며 절대 공유되지 않음

 

핸들러 API

Mysql이 InnoDB 스토리지 엔진과 데이터를 주고받기 위해 사용하는 내부 API. SQL레벨이 아님

쓰기 또는 읽기 요청을 핸들러 요청이라 부름

쿼리 실행 시 얼마나 많은 데이터 작업이 있었는지 SHOW GLOBAL STATUS LIKE 'Handler%' 로 확인 가능함

이렇게나온당

Handler_read_next같은 값이 높으면 풀스캔 가능성이 높음

 

플러그인 스토리지 엔진

InnoDB 외에도 사용자 정의 스토리지 엔진 플러그인을 사용 가능함

Mysql의 유연성과 확장성의 핵심 특징 중 하나로, 검색 최적화용이나 보안용 등등 여러가지 있음

회사 또는 개발자가 직접 개발하는 것도 가능함

쿼리가 실행되는 거의 대부분의 작업이 Mysql 엔진에서 처리되고, 마지막 데이터 읽기/쓰기 작업만 스토리지 엔진이 처리함

'컴포넌트' 라는 것도 있는데, Mysql 8.0에서 새로 도입됐고 기존 플러그인의 초기화 어렵고, 안전성이 부족한 단점을 보완한 버전임

 

쿼리 실행 구조 요약

1. 파서: 문장을 최소 단위 토큰으로 분리

2. 전처리기: 문법 및 구조적인 문제 확인

3. 옵티마이저: 실행 계획 수립(인덱스, 조인 순서 결정 등등)

4. 실행 엔진: 실행 계획에 따라 핸들러에 요청

5. 핸들러 API: 스토리지 엔진과 직접 데이터 I/O 수행함

 

위에 나온 Handler_read_next 값이 높을 수록 풀스캔 가능성이 높은 이유:

실행 엔진이 핸들러에게 요청을 많이 보낼 수록(옵티마이저의 실행 계획 맨 오른쪽에 임시파일 임시테이블 등등..) 값이 폭증하게 되어서, Handler로그로 쿼리 동작을 예측할 수 있는거임

 

read_next 외에도 로그 기반 힌트는 많은데 대표적으로 정리하자면

Handler_read_next: 다음 row 읽기 요청, 인덱스가 없거나 where 조건이 무시된 경우

Handler_read_rnd_next: 테이블 전체 스캔 중 임의 행에 순차 접근한 횟수, 임시 테이블 사용 시 자주 발생함

Handler_read_key: 인덱스를 통한 정확한 키 조회, 인덱스를 효율적으로 활용한 경우

Created_tmp_disk_tables: 디스크 기반 임시 테이블 생성 횟수, Group by, Order by, Distinct 등등.. 메모리 한계 시 발생함

Created_tmp_tables: 메모리 임시 테이블 생성 횟수, SQL 성능 부담은 적은 편임

 

쿼리 캐시

변경 시 Invalidating 비용이 크고 동시성이 저하돼서 8.0부터는 완전 제거되어서

캐시를 원한다면 어플리케이션 레벨, Redis 등으로 우회하자

 

스레드 풀

Mysql 엔터프라이즈에서만 기본 제공되고, 커뮤니티 에디션은 Percona server에서 제공함

장점은 OS 스레드와 비슷함: 컨텍스트 스위칭 비용 줄여주고, 따라서 제한된 수의 스레드로 요청을 효율적으로 처리하고 등등

가용 스레드가 많아진다고 꼭 성능이 좋아지는 건 아니기 때문에 CPU 수 대비 적절한 pool 크기 설정이 중요함.

스레드가 많아진다고 성능이 좋아지는 게 아닌 이유

1. 결국 OS 스케줄러는 각 스레드를 코어에 스케줄링시켜서 실행해야되는데,
아무리 스레드 수가 많아도 동시에 실행 가능한 건 CPU 코어 수 만큼임.
나머지 스레드는 대기하면서 차례를 기다려야 함..

2. OS는 어떤 스레드를 지금 실행할지 선택해야 하는데 이 때 스레드의 TCB 등등을 복원, 저장하는 작업이 필요함. 이게 컨텍스트 스위칭이고, 결국 스레드 수가 많아질 수록 컨텍스트 스위칭 비용이 증가함

3. 스레드 하나 당 OS의 스택 메모리를 사용함

성능적으로는 이러하고, 공유 자원이 존재하는 경우 락이나 동기화 비용도 생각해야 함 .. .