Real MySQL 8.0 1권
『Real MySQL 8.0』은 『Real MySQL』을 정제해서 꼭 필요한 내용으로 압축하고, MySQL 8.0의 GTID와 InnoDB 클러스터 기능들과 소프트웨어 업계 트렌드를 반영한 GIS 및 전문 검색 등의 확장 기능들을 추가로 수록했다. 또한 단순 SQL 문법이나 쿼리 작성보다는 MySQL 서버를 활용하는 프로젝트에서 꼭 필요한 경험과 지식을 전달하는 데 집중했다.
4. 아키텍처
4. 아키텍처
MySQL 엔진 아키텍처
MySQL 엔진 아키텍처
- MySQL 서버는 사람의 머리 역할을 담당하는 MySQL 엔진과 손발 역할을 담당하는 스토리지 엔진으로 구분
- 스토리지 엔진의 핸들러 API를 만족하면 누구나 스토리지 엔진을 구현해 MySQL 서버에 추가해서 사용 가능
MySQL 엔진
- 클라이언트로부터의 접속 및 쿼리 요청을 처리하는 커넥션 핸들러, SQL 파서, 전처리기, 옵티마이저가 중심을 이룸
- 표준 SQL 문법을 지원해 표준 문법을 지켜 작성된 쿼리는 타 DBMS와 호환되어 실행 가능
스토리지 엔진
-
실제 데이터를 디스크 스토리지에 저장하거나 데이터를 읽어오는 역할을 수행
-
MySQL 엔진은 하나만 사용할 수 있지만 스토리지 엔진은 여러 개를 동시에 사용 가능
-
다음 명령어를 통해 테이블에 사용할 스토리지 엔진을 지정할 수 있음
CREATE TABLE test_table (fd1 INT, fd2 INT) ENGINE=INNODB;
핸들러 API
- MySQL 엔진의 쿼리 실행기에서 데이터를 쓰거나 읽을 때 각 스토리지 엔진에 요청을 하는데 이를 핸들러(Handler) 요청으로 부름
- 핸들러 API를 통해 레코드 작업이 얼마나 수행됐는지 확인하는 명령어
SHOW GLOBAL STATUS LIKE 'Handler%';
4. 아키텍처
MySQL 스레딩 구조
MySQL 스레딩 구조
-
MySQL 서버는 프로세스가 아닌 스레드 기반으로 동작
-
스레드는 크게 Foreground 스레드와 Background 스레드 두 종류로 구분
-
MySQL 서버의 실행 중인 스레드 목록 조회 명령어
SELECT thread_id, name, type, processlist_user, processlist_host FROM performance_schema.threads ORDER BY type, thread_id; -
사용자의 요청을 처리하는 Foreground 스레드는
thread/sql/one_connection스레드 -
Background 스레드의 개수는 MySQL 서버 설정으로 조절 가능
Foreground 스레드 (클라이언트 스레드)
- MySQL 서버에 연결된 클라이언트의 수만큼 존재함
- 각 클라이언트 유저가 요청한 쿼리 문장을 처리
- 사용자가 작업을 마친 후 커넥션을 종료하면 해당 커넥션을 담당하던 스레드는 스레드 캐시로 돌아감
- 단, 스레드 캐시에 일정 개수 이상의 대기 중인 스레드가 존재하면 캐시에 넣지 않고 스레드를 종료시킴
- 스레드 캐시에서 항상 일정한 스레드 개수 유지
- 유지할 스레드 개수는
thread_cache_size시스템 변수로 설정 가능
- Foreground 스레드는 데이터를 MySQL의 데이터 버퍼나 캐시로부터 조회
- 버퍼나 캐시에 없는 경우 직접 디스크의 데이터나 인덱스 파일로부터 조회한 후 작업 처리
- MyISAM 테이블은 디스크 쓰기 작업까지 Foreground 스레드가 처리
- InnoDB 테이블은 데이터 버퍼와 캐시까지는 Foreground 스레드가 처리하고 디스크 기록은 Background 스레드가 처리
Background 스레드
- InnoDB에서 여러 가지의 작업을 Background 스레드로 처리
- Insert Buffer를 병합하는 스레드
- 로그를 디스크로 기록하는 스레드
- InnoDB 버퍼 풀의 데이터를 디스크에 기록하는 스레드
- 데이터를 버퍼로 읽어 오는 스레드
- 잠금이나 데드락을 모니터링하는 스레드
- 가장 중요한 스레드는 로그 스레드와 버퍼의 데이터를 디스크로 기록하는 쓰기 스레드
- MySQL 5.5 버전부터 쓰기 스레드와 읽기 스레드의 개수를 2개 이상 지정할 수 있음
innodb_read_io_threads: 데이터를 주로 클라이언트 스레드에서 처리되기에 많이 설정할 필요 없음innodb_write_io_threads: 많은 작업을 Background로 처리하기에 일반적인 내장 디스크 활용 시 2~4개 권장
- 사용자의 요청을 처리하는 도중 데이터 쓰기 작업은 지연(버퍼링)되어 처리 가능
- 데이터의 읽기 작업은 절대 지연될 수 없음
- 예시: SELECT 쿼리 실행 후 요청된 SELECT 응답을 10분 뒤에 돌려주는 DBMS는 존재하지 않음
- 일반적인 상용 DBMS는 대부분 쓰기 작업을 버퍼링해 일괄 처리하는 기능이 탑재됨
- 단, 예외로 MyISAM의 경우 사용자 스레드가 쓰기 작업까지 함께 처리하도록 설계
- InnoDB에서는
INSERT,UPDATE,DELETE쿼리로 데이터가 변경되는 경우 데이터가 디스크에 완전히 기록될 때까지 기다리지 않아도 됨- MyISAM에서는 일반적인 쿼리는 쓰기 버퍼링 기능 사용 불가
4. 아키텍처
메모리 할당 및 사용 구조
메모리 할당 및 사용 구조
- MySQL 메모리 공간은 글로벌 메모리 영역과 로컬 메모리 영역으로 구분할 수 있음
- 글로벌 메모리 영역은 MySQL 서버가 시작되면서 운영체제로부터 할당받음
- 글로벌 메모리 영역과 로컬 메모리 영역은 스레드가 공유해서 사용하는 공간인지 여부에 따라 구분됨
글로벌 메모리 영역
- 일반적으로 클라이언트 스레드의 수와 무관하게 하나의 메모리 공간만 할당
- 필요에 따라 2개 이상의 메모리 공간을 할당받을 수 있으나 클라이언트 스레드 수와 무관
- 생성된 글로벌 영역이 N개라 해도 모든 스레드에 의해 공유됨
- 대표적인 글로벌 메모리 영역
- 테이블 캐시
- InnoDB 버퍼 풀
- InnoDB 어댑티브 해시 인덱스
- InnoDB 리두 로그 버퍼
로컬 메모리 영역
- 세션 메모리 영역이라 표현하며 MySQL 서버에 존재하는 클라이언트 스레드가 쿼리를 처리하는 데 사용하는 메모리 영역
- 대표적으로 커넥션 버퍼와 정렬 버퍼 등이 존재함
- 클라이언트가 MySQL 서버에 접속하면 클라이언트 커넥션으로부터의 요청 처리를 위해 스레드를 하나씩 할당
- 클라이언트 스레드가 사용하는 메모리 공간이라고 해서 클라이언트 메모리 영역이라고 부름
- 클라이언트와 MySQL 서버와의 커넥션 = 세션 (세션 메모리 영역)
- 각 클라이언트 스레드별로 독립적으로 할당되며 스레드간 공유가 이뤄지지 않음
- 각 쿼리의 용도별로 필요할 때만 공간이 할당되고 필요하지 않으면 MySQL이 메모리 공간을 할당하지 않음
- 커넥션이 열려 있는 동안 계속 할당된 상태로 남아 있는 공간이 존재함
- 커넥션 버퍼나 결과 버퍼
- 쿼리를 실행하는 순간에만 할당한 후 다시 해제하는 공간이 존재함
- 소트 버퍼나 조인 버퍼
- 커넥션이 열려 있는 동안 계속 할당된 상태로 남아 있는 공간이 존재함
- 대표적인 로컬 메모리 영역
- 정렬 버퍼
- 조인 버퍼
- 바이너리 로그 캐시
- 네트워크 버퍼
4. 아키텍처
플러그인 스토리지 엔진 모델
플러그인 스토리지 엔진 모델
- 전문 검색 엔진을 위한 검색어 파서