: MySql 서버는 MySql 엔진
과 스토리지 엔진
으로 나눌 수 있다.
- 클라이언트의 접속 및 쿼리 요청을 처리하는
커넥션 핸들러
- sql 쿼리를 알맞은 토큰으로 분리 후 트리로 변환하는
SQL 파서
- 토큰 트리를 문법으로 인식해, 문법적 오류가 있는지 확인하는
전처리기
- 쿼리 실행문을 최적화하는
옵티마이저
- 실제 파일 시스템과 관련된 일을 함
- Mysql 엔진은 하나지만, 스토리지 엔진은 동시에 여러개를 사용할 수 있다.
⭐ MySql 엔진
과 스토리지 엔진
이 데이터를 주고 받기 위해서는 핸들러 API
를 이용한다.
mysql> SHOW GLOBAL STATUS LIKE 'Handler%';
위의 명령어를 사용하면, 이 핸들러 api 를 통해 어떤 데이터 작업이 있었는지 알 수 있다.
정리하다 보니, mySql 의 이런 구조가 컴파일러의 구조와 역할이 거의 유사하다는 것을 느꼈다.
<역할> 컴파일러는 코드를 받아 os를 다루기 위한 중간 어셈블리 코드(ISA)로 변환한다.
MySQL 엔진
은 파일 시스템(os)을 다루기 위해HandlerApi
를 생성한다.<구조>
MySQL 엔진
의 세부적인 동작 원리도 컴파일러와 비슷해보인다.컴파일러의
Front
는 아래와 같이 나뉜다.
- 주어진 HLL를 의미있는 토큰으로 분리하는
Lexical Analyzer(scanner)
- 토큰 스트림을 받아 Syntax tree 를 구성하고 symbol table 을 만드는
Syntax Analyzer(parser)
- symbol table을 참고하여 type checking 과 같은 문법의 의미를 평가하는
Semantic Analyzer
Back
과의 일종의 api 인 intermediate code 를 생성하는Intermediate Code Generator
컴파일러의
Back
은 intermediate code를 받아서 ISA 코드를 생성하고 코드를 최적화한다.mySql 엔진:
SQL 파서
-전처리기
-옵티마이저
컴파일러 :Lexical Analyzer(scanner)
-Syntax Analyzer(parser)
-Semantic Analyzer
-Back(optimizing)
: 프로세스 기반이 아닌 스레드 기반으로 동작, 포그라운드
와 백그라운드
로 구분할 수 있다.
- 최소 접속된 클라이언트의 수만큼 존재(하나의 커넥션의 작업을 병렬로 처리할 수도 있음.)
- 커넥션을 종료하면 스레드 캐시로 돌아가거나 종료. (스레드 캐시에 저장된 스레드 수를 일정하게 유지한다. 시스템 변수로 설정 가능)
- 데이터 버퍼나 캐시로부터 데이터를 가져오는 작업을 주로 한다.
- 여러가지 작업을 처리하지만 가장 중요한 것은
로그 스레드
와쓰기 스레드
이다. - mysql 5.5 버전부터
쓰기 스레드
를 2개 이상 지정할 수 있고,쓰기 스레드
는 아주 많은 작업을 처리하기 때문에, 일반적인 재장 디스크를 사용할 때는 2~4개 정도로 충분히 설정하는 것이 좋다. - 읽기 지연은 절대 일어나지 않지만, os 여건에 따라 쓰기 지연을 일어날 수 있다. 따라서 보통 쓰기 작업을 버퍼링 해서 일괄처리 하도록 설계되어 있다. => 데이터가 디스크에 완전히 저장되는 걸 기다리지 않아도 된다! (InnoDB)
- 하지만 MyISAM 은 사용자 스레드가 쓰기작업까지 함께 처리하도록 설계돼 있어서, 일반적인 쿼리는 쓰기 버퍼링을 이용할 수 없다.
⭐ 프로세스 기반 db 와 쓰레드 기반 db 의 차이?
postgreSQL 은 프로세스 기반 db 라고 한다.
- single-process & multi-thread 기반인 경우, 프로세스 충돌이 일어났을 때 db 자체가 그냥 죽어버리게 된다
- 쓰레드 관련 라이브러리가 OS 마다 상이하기 때문에 자잘한 오류가 많이 발생한다. (예로 BSD 계열 리눅스는 mysql 관련 해당 오류가 발생한다고)
- multi-thread 기반 db 는 시스템 자원에 대한 경합이 너무 심하다. (이 경합을 잘 조율하는 게 기술적으로 어렵기도 하기 때문에 버그가 자주 발생하기도 한다고) 등의 이유로 멀티 프로세스 방식을 채택하고 있다고 한다.
대신
- 프로세스를 fork 하는 비용이 쓰레드에 비해 너무 크다. => 속도도 느림
- 하나의 쿼리에 대해서 병렬처리를 할 수 없다. (멀티 프로세스로 병렬처리를 구현하더라도, 비효율적이다.)
- 멀티 쓰레드가 병렬처리 시에 쓰레드 간 소통이 더 빠르다. 과 같은 단점들이 존재한다.
아마 멀티 프로세스를 사용하는 이유는 최적의 속도보다는, 시스템의 안정성을 추구하기 위함인 듯 하다. 시중에 다중 프로세스와 다중 쓰레드를 동시에 지원하는 db 도 있던 것 같았는데, 안정성과 속도를 적절히 잘 배합하려는 시도인 듯 하다.
: 글로벌 메모리 영역
과, 로컬 메모리 영역
으로 나뉜다.
- 서버가 시작되면서 운영체제로부터 할당된다.
- 모든 스레드에 의해 공유된다.
- 보통 하나의 메모리 공간만 할당되지만, 필요에 따라 2개 이상의 공간을 할당받을 수도 있다.
- 클라이언트 스레드가 쿼리를 처리하는데 사용하는 메모리 영역이다. => 클라이언트 메모리 영역, 세션 메모리 영역이라고도 한다.
- 스레드 별로 공유되지 않는다.
- 쿼리의 용도별로 필요할 때만 공간이 할당된다. 예로 커넥션버퍼나 결과버퍼는 커넥션이 열려있는 동안 계속 할당된 상태로 남아있고, 소트 버퍼나 조인 버퍼는 해당 쿼리를 실행하는 순간에만 할당하고 해제한다.
- MySQL 은 플러그인 형태로 다양한
스토리지 엔진
을 제공한다. - 스토리지 엔진 뿐만 아니라, 인증이나 파서(parser) 등도 플러그인 형태로 제공되고, 직접 개발해서 사용할 수 있다.
- 스토리지 엔진의
데이터 읽기/쓰기
작업은 대부분 1건의 레코드 단위로 처리된다.group by
나order by
등 복잡한 처리는 MySQL 엔진의쿼리실행기
에서 처리된다.
⭐ 하나의 쿼리 작업은 여러 하위 작업으로 나뉘는데, 각 하위 작업이 MySQL 엔진 영역에서 처리되는지 아니면 스토리지 엔진 영역에서 처리되는지 구분할 줄 알아야한다.
mysql> SHOW ENGINES;
mysql> SHOW PLUGINS;
위와 같은 명령어로 설치되어 있는 스토리지 엔진과 플러그인을 확인할 수 있다.
: 기존 플러그인 모델의 단점을 대체하기 위해 등장.
- 플러그인은 MySQL 서버와 인터페이스할 수 있고, 플러그인끼리는 통신할 수 없다.
- MySQL 서버의 변수나 함수를 직접 호출하기 때문에 안전하지 않다.
- 상호 의존관계를 설정할 수 없어서 초기화가 어렵다.
쿼리 파서
- sql 쿼리를 알맞은 토큰으로 분리 -> 트리 형태로 변환 - 쿼리 문장의 기본 문법 오류를 인식전처리기
- 토큰 트리를 문법으로 인식해, 문장에 구조적인 문제가 있는지 확인. - 토큰을 테이블 이름이나, 내장 함수 등과 같은 개체를 매핑해 해당 객체의 존재 여부를 파악. - 또는 해당 객체에 대한 접근 권한을 파악. - 존재하지 않거나 접근 불가능한 토큰은 걸러진다.옵티마이저
- sql 문 최적화. dbms 의 두뇌에 해당.실행엔진
- 옵티마이저가 두뇌라면 실행엔진과 핸들러는 손과 발에 비유할 수 있다. - 옵티마이저가 Group By 를 처리하기 위해 임시 테이블을 사용하기로 결정한다고 했을 때,- 실행 엔진이 핸들러에게 임시 테이블을 만들라고 요청
- 다시 실행 엔진은 where 절에 일치하는 레코드를 읽어오라고 핸들러에게 요청
- 읽어온 레코드들을 1번에서 준비한 임시 테이블로 저장하라고 다시 핸들러에게 요청
- 데이터가 준비된 임시 테이블에서 필요하 방식으로 데이터를 읽어 오라고 핸들러에게 다시 요청
- 최종적으로 실행 엔진은 결과를 사용자나 다른 모듈로 넘김
⭐ MySQL 8.0 으로 올라오면서 쿼리 캐시는 완전히 제거됐다!
- 기존에는 실행 결과를 메모리에 캐시했다.
- 데이터가 변경되었을 때 캐시에 저장된 결과중에서 변경된 테이블과 관련된 것들을 모두 삭제해야한다.
- 심각한 동시 처리 성능 저하 유발. 및 버그 발생 등의 문제.
- 내부적으로 사용자의 요청을 처리하는 스레드 개수를 줄여 동시 처리되는 요청이 많다 하더라도, CPU가 제한된 개수의 스레트 처리에만 집중할 수 있게 해서 서버의 자원 소보를 줄이는 것이 목적
- 엔터프라이즈 에디션은 스레드 풀을 제공하지만, 커뮤니티 에디션은 Percona Server 에서 제공하는 플러그인 형태의 스레드 풀을 이용해야한다.
데이터 딕셔너리(메타데이터)
: 테이블의 구조 정보와 스토어드 프로그램 등의 정보. 파일 기반으로 관리했었다. 파일 기반의 메타데이터는 트랜잭션을 지원하지 않기 때문에 테이블을 생성 또는 변경 중에 서버가 비정상 종료되면 테이블 깨지는 현상이 있었다.- 8.0 버전부터는
데이터 딕셔너리
를 모두InnoDB
의 테이블에 저장하도록 개선됐다.시스템 테이블
과데이터 딕셔너리
를mysql
DB에 저장한다.mysql
DB는 통째로mysql.ibd
라는 이름의 테이블스페이스에 저장된다. 시스템 정보라 해당 db 에는 사용자가 접근할 수 없다. MyISAM
이나CSV
등과 같은 스토리지 엔진의 메타 정보는 여전히 저장할 공간이 필요하다.