- MySQL 서버는 MySQL 엔진과 스토리지 엔진으로 이루어져 있음
MySQL 엔진
- 커넥션 핸들러 : 클라이언트의 접속과 쿼리 요청을 처리함
- SQL 파서, 전처리기
- 옵티마이저 : 쿼리 최적화 담당
스토리지 엔진
- 실제 디스크 스토리지에 데이터 저장
- 디스크 스토리지로부터 데이터 읽어오기
MySQL 엔진은 하나지만, 스토리지 엔진은 동시에 여러개 사용 가능
테이블 생성 시 다음과 같이 스토리지 엔진을 지정할 수 있다. 해당 테이블에 대한 읽기, 변경 작업은 지정된 스토리지 엔진으로 처리하게 된다.
CREATE TABLE test (id INT, name VARCHAR(30)) ENGINE=INNODB;
- MySQL 엔진이 스토리지 엔진에서 데이터를 읽어오거나 저장하기 위해 핸들러를 거친다.
- GROUP BY나 ORDER BY 와 같은 복잡한 처리는 스토리지 엔진이 아닌, MySQL 엔진의 쿼리 실행기에서 처리된다.
- 하나의 쿼리 작업은 여러 하위 작업으로 나뉜다. 각 하위 작업은 MySQL 엔진과 스토리지 엔진에 의해서 실행된다.
SHOW ENGINES;
- 위의 명령어로 설치된 MySQL 서버에서 지원되는 스토리지 엔진을 확인할 수 있다.
핸들러 API
- MySQL 엔진이 쿼리 실행기에서 데이터를 읽거나 쓸 때, 각 스토리지 엔진에 쓰기나 읽기를 요청한다.
즉, Handler API를 이용해서 MySQL 엔진과 스토리지 엔진이 데이터를 주고받는 것
MySQL 스레딩 구조
MySQL 서버는 프로세스가 아닌 스레드 기반으로 작동한다.
- Foreground thread
- Background thread
- performance_schema.threads 를 통해서 MySQL 서버에서 실행 중인 스레드 목록을 볼 수 있음
Foreground thread (클라이언트 스레드)
- 주로 각 클라이언트가 요청하는 쿼리를 처리한다.
- thread_cache_size 시스템 변수로 스레드 캐시에 유지할 수 있는 최대 스레드 개수 설정 가능
- 클라이언트가 작업을 다 마치고 커넥션을 종료하면 -> 해당 스레드는 thread cache로 돌아간다.
- Foreground 스레드는 MySQL의 데이터 버퍼나 캐시로부터 데이터를 갖고 오고, 데이터가 없다면 디스크의 데이터나 인덱스 파일로부터 읽어온다.
- InnoDB는 버퍼나 캐시까지만 Foreground thread가 처리하고, 버퍼로부터 디스크로 기록하는 작업은 백그라운드 스레드가 처리함
- Foreground thread = 사용자 스레드
- 즉, 클라이언트의 요청을 처리해주는 스레드, 클라이언트에 할당되는 스레드
Background thread
- 로그를 디스크에 기록하고, InnoDB 버퍼풀의 데이터를 디스크에 기록, 데이터를 버퍼로 읽어오기, 잠금이나 데드락 모니터링 등의 작업을 수행하는 스레드가 백그라운드 스레드이다.
- 대부분 쓰기작업은 백그라운드 스레드가 진행하고, 읽기 작업은 포그라운드 스레드가 작업한다.
- 쓰기작업은 지연되어 처리가 가능하나, 읽기작업은 지연처리가 불가능하다.
MySQL의 메모리 공간과 구조
- 글로벌 메모리 영역과 로컬 메모리 영역으로 나뉜다.
글로벌 메모리 영역
- MySQL 서버가 시작되면서 운영체제로부터 시스템 변수로 설정한 만큼 할당된다.
- 클아이언트 스레드 수와 관계 없이 하나의 메모리 공강만 할당된다.
- 여러개의 글로벌 메모리 영역기 생성되라고 모든 스레드에 의해 공유된다.
- 테이블 캐시, Inno버퍼 풀, InnoDB 리두 로그버퍼 등이 해당됨
로컬 메모리 영역
- 세션 메모리 영역, 클라이언트 메모리 영역이라고도 불림
- 클라이언트 스레드가 쿼리를 처리하는데 사용하는 메모리 영역이다
- 각 클라이언트 스레드멸로 독립적으로 할당된다. 공유되는 공간이 아님
- 정렬 버퍼, 조인 버퍼, 바이너리 로그 캐시, 네트워크 버퍼 등이 해당됨
쿼리 실행 구조
쿼리 파서
- 사용자로부터 요청된 쿼리 문장을 토큰으로 분리해서 트리 형태 구조로 만든다.
토큰이란, MySQL이 인식할 수 있는 최소 단위의 어휘나 기호임
- 쿼리문의 Syntax error는 이 과정에서 발견된다.
전처리기
- 파서 과정에서 만들어진 파서 트리를 기반으로 쿼리문의 구조적인 것을 검증한다.
- 각 토큰을 table 이름, column 이름, 내장 함수 등과 매핑해서 각 객체의 존재여부, 접근 권한 등을 확인
옵티마이저
- 쿼리문을 저렴한 비용으로 가장 빠르게 처리하는 것을 결정
실행엔진
- 옵티마이저에 의해 최적화된 계획대로 각 핸들러에게 요청하고, 받은 결과를 또 다른 핸들러 요청의 입력으로 연결하는 역할
핸들러 (스토리지 엔진)
- 핸들러는 MySQL 실행 엔진의 요청에 따라 데이터를 디스크에 저장, 읽기를 한다.
- 핸들러는 곧 스토리지 엔진이다.
- MyISAM 테이블을 조작하면 핸들러는 MyISAM 스토리지 엔진이고, InnoDB 테이블을 조작하면 핸들러가 InnoDB 스토리지 엔진임
쿼리 캐시
- SQL 실행 결과를 메모리에 캐시하고, 동일한 SQL에 대한 결과를 빠르게 반환
-> 캐시에 저장된 것 중 변경된 테이블과 관련된 데이터는 invalidate 해야한다. -> 동시 처리 성능 저하 발생
- 이와 같은 문제로 MySQL 8.0 부터는 쿼리 캐시 기능이 제거되고, 관련된 시스템 변수도 제거됨
학습한 것을 상기시키며 정리했습니다. 출처: Real MySQL 8.0
'DB > MySQL' 카테고리의 다른 글
deadlock found when trying to get lock 에러 해결 (1) | 2024.07.16 |
---|---|
오랜만에 MySQL 접속하니 마주한 에러들 해결 정리 (0) | 2023.03.29 |
case when exists (0) | 2022.03.27 |