MySQL은 다른 DBMS와 비교해서 그 구조가 상이하다.
(출처 : https://github.com/bestdevhyo1225/dev-log/blob/master/MySQL/MySQL-Architecture.md)
MySQL 서버는 크게 MySQL 엔진, 스토리지 엔진으로 구별한다.
MySQL의 쿼리 파서나 옵티마이저 등과 같은 기능들을 MySQL 엔진에 포함한다.
MySQL 엔진은 SQL문장을 분석, 최적화 한다면 스토리지 서버는 실제 데이터를 저장하고 읽어오는 부분을 전담한다.
ENGINE={ENGINE_NAME} (e.g. INNODB)
를 작성하면 해당 테이블의 모든 읽기, 쓰기 작업들을 정의된 스토리지 엔진이 처리, 예시에서는 InnoDB 엔진을 사용하도록 정의한다.MySQL 엔진에서 데이터를 쓰거나 읽어야 할 때 각 스토리지 엔진에 I/O 요청을 하는데, 이것을 핸들러 요청이라 하며, 여기서 사용되는 API가 핸들러 API이다.
핸들러 API를 통한 데이터 작업 횟수를 SHOW GLOBAL STATUS LIKE 'Handler%';
로 확인할 수 있다.
MySQL 서버는 스레드 기반으로 작동하며, Foreground, Background Thread로 구분한다.
다음 쿼리로 performance_schema
데이터베이스의 threads
테이블에 있는 실행 중인 스레드의 목록을 확인할 수 있다;
SELECT thread_id, name, type, processlist_user, processlist_host
FROM performance_schema.threads ORDER BY type, thread_id;
thread/sql/one_connection
만 실제 사용자의 요청을 처리한다.thread_cache_size
시스템 변수로 설정한다.그래서 Background Thread가 버퍼에서 디스크 쓰기까지 담당해야 하는 InnoDB의 경우 이러한 작업들이 Background에서 일어난다:
MySQL 5.5부터 io_read_thread
와 io_write_thread
를 2개 이상 지정할 수 있으며, 시스템 변수에 innodb_write_io_threads
와 innodb_read_io_threads
로 설정한다.
InnoDB에서 읽는 작업은 Client Thread에서 처리하기 때문에 많이 필요없지만, Write Thread는 Background에서 많은 작업을 처리하기 때문에 Write Thread를 디스크에 적합하게 조율한다.
쓰는 작업은 지연될 수 있지만, 읽는 작업은 지연될 수 없다. → 대부분의 DBMS는 쓰기 작업을 버퍼링해서 일괄 처리함. InnoDB 또한 그러나, MyISAM에서는 지원하지 않는다.
메모리 공간은 크게 글로벌 메모리, 로컬 메모리로 구분한다.
글로벌 메모리는 MySQL 서버가 시작되면서 운영체제로부터 할당된다.
Client Thread 수와 무관하게 하나의 메모리 공간만 할당받는다.
필요하면 복수의 메모리 공간을 할당받을 수 있지만, Client Thread와는 무관하며, 개수와 상관없이 모든 Thread에 공유된다.
종류
MySQL 서버의 Client Thread가 쿼리를 처리하는 데 사용하는 메모리.
종류
MySQL에는 스토리지 엔진 뿐만 아닌 다양한 플러그인을 구현할 수 있으며, 또한 직접 커스터마이징한 스토리지 엔진도 구현할 수 있다.
위의 그림과 같이 스토리지 엔진은 데이터 읽기/쓰기에 전담하는데, 여기서 이 작업은 대부분 1건의 레코드 단위로 처리된다.
결국 스토리지 엔진의 교체는 뒤의 데이터 읽기/쓰기 부분만 변경되며, 나머지 부분은 대부분은 동일하다.
Docker mysql:latest
(2023-04-01) 기준 지원되는 스토리지 엔진들은 다음과 같다;
Support에 YES, DEFAULT이면 사용 가능한 스토리지 엔진이며, NO인 스토리지 엔진의 경우 사용하려면 MySQL를 다시 빌드해야 한다.
이외에도 SHOW PLUGINS;
를 통해 스토리지 엔진을 포함한 다양 기능의 플러그인들을 볼 수 있다.
또한 몇가지 단점이 있는데, 이를 보완한것이 컴포넌트이다.
사용자 요청으로 들어온 쿼리 문장을 토큰으로 분리해 트리 형태의 구조로 만들어 내는 작업을 의미한다.
이 과정에서 쿼리 문법 오류를 발견하고 오류 메시지를 전달하게 된다.
토큰 : MySQL이 인식할 수 있는 최소 단위의 어휘나 기호
만들어진 파서 트리를 기반으로 쿼리 문장의 구조적 문제점을 확인한다. 토큰을 테이블명, 칼럼명, 내장 함수 등으로 매핑해서 객체들의 존재 여부와 접근 가능 여부를 확인해서 걸러낸다.
사용자의 요청으로 들어온 쿼리 문장을 저렴한 비용으로 가장 빠르게 처리하도록 수행하는 역할을 담당하며, DBMS에서 옵티마이저의 역할은 매우 중요하고 영향력 또한 크다.
옵티마이저의 계획대로 각 핸들러에게 요청하고 받은 결과들을 종합해서 다시 다른 핸들러들의 요청에 입력으로 넣어준다.
핸들러는 MySQL 서버의 가장 밑단에서 MySQL 실행 엔진의 요청에 따라 데이터를 디스크로 저장하고 읽어오는 역할을 맡는다.
쿼리 캐시는 SQL 실행 결과를 메모리에 캐시하고, 동일 SQL 쿼리가 실행되면 테이블을 읽지 않고 즉시 결과를 반환한다.
장점
단점
그리고 MySQL 서버의 성능 개선 과정에서 많은 버그의 원인이 되어
결국 MySQL 8.0 이후로 쿼리 캐시는 MySQL에서 제거됐다.
thread_pool_size
시스템 변수로 스레드 그룹의 개수를 조정할 수 있다.thread_pool_stall_limit
시스템 변수에 정의된 시간 안에 작업을 끝내지 못하면 새로운 스레드를 스레드 그룹에 추가한다. 그러나 이는 풀의 최대 스레드 수를 넘지 않는다메타데이터 (데이터 딕셔너리) : 데이터베이스의 테이블 구조 정보, 스토어드 프로그램 등의 정보
~ 5.7버전
MySQL 8.0
mysql.ibd
라는 테이블 스페이스에 저장된다.