Computer Science/Database

Engine=InnoDB는 뭘 지정해주는 걸까 - MySQL 엔진과 스토리지 엔진

이진2 2023. 7. 9. 23:05

MySQL 아키텍처

  • MySQL 서버는 MySQL 엔진, 스토리지 엔진으로 구분
  • 스토리지 엔진은 핸들로 API를 만족하면 누구든 구현해서 서버에 추가 가능

 

MySQL 엔진 아키텍처

출처: https://dev.mysql.com/doc/refman/8.0/en/images/mysql-architecture.png

 

MySQL 엔진

MySQL 엔진은 아래의 역할들을 수행하며 요청된 SQL 문장을 분석, 최적화하는 핵심 처리를 함

  • 커넥션 핸들러: 클라이언트로부터의 접속 및 쿼리 요청을 처리
  • SQL 파서
  • 전처리기
  • 옵티마이저: 쿼리를 최적화 하여 실행

 

스토리지 엔진

  • 실제 데이터를 디스크 스토리지에 저장하거나 데이터를 읽어오는 부분을 전담
  • 스토리지 엔진은 여러 개를 동시에 사용할 수 있다
  • 각 스토리지 엔진은 성능 향상을 위해 키 캐시나 InnoDB 버퍼 풀과 같은 기능을 내장
mysql> CREATE TABLE test_table (fb1 INT, fb2 INT) ENGINE=INNODB;

 

핸들러 API

  • 핸들러 API: MySQL 엔진의 쿼리 실행기에서 데이터를 쓰거나 읽을 때 스토리지 엔진에 요청하는 API
  • InnoDB 스토리지 엔진 또한 이 핸들러 API를 이용해 MySQL 엔진과 데이터를 주고받음

 

MySQL 스레딩 구조

출처: Real MySQL 1권 - 그림 4.2

MySQL 서버는 프로세스 기반이 아니라 스레드 기반으로 작동하며, 크게 포그라운드 스레드와 백그라운드 스레드로 구분한다

 

포그라운드 스레드(클라이언트 스레드)

  • 주로 클라이언트 사용자가 요청하는 쿼리 문장을 처리
  • 최소 MySQL 서버에 접속된 클라이언트의 수만큼 존재
  • 커넥션이 종료되면 스레드는 다시 스레드 캐시로 되돌아간다. 스레드 캐시에 일정 개수 이상이 대기 중이면 캐시에 넣지 않고 종료시켜 일정 개수의 스레드만 캐시에 존재하게 한다.

백그라운드 스레드

  • 인서트 버퍼를 병합하는 스레드
  • 로그를 디스크로 기록하는 스레드
  • InnoDB 버퍼 풀의 데이터를 디스크에 기록하는 스레드
  • 데이터를 버퍼로 읽어 오는 스레드
  • 잠금이나 데드락을 모니터링하는 스레드

InnoDB에서도 데이터를 읽는 작업은 주로 클라이언트 스레드에서 처리되기 때문에 읽기 스레드는 많이 설정할 필요 없다.

사용자의 요청을 처리하는 도중 데이터의 쓰기 작업은 지연(버퍼링)되어 처리될 수 있지만 데이터의 읽기 작업은 절대 지연될 수 없다.


메모리 할당 및 사용 구조

출처: Real MySQL 1권 - 그림 4.3

  • 글로벌 메모리 영역과 로컬 메모리 영역으로 구분
  • 글로벌 메모리 영역의 모든 메모리 공간은 MySQL 서버가 시작되면서 운영체제로부터 할당.

 

글로벌 메모리 영역

  • 클라이언트 스레드 수와 무관하게 하나의 메모리 공간만 할당
  • 필요에 따라 2개 이상의 메모리 공간을 할당받을 수 있지만 클라이언트의 스레드 수와는 무관하다.
  • 영역
    • 테이블 캐시
    • InnoDB 버퍼 풀
    • InnoDB 어댑티브 해시 인덱스
    • InnoDB 리두 로그 버퍼

로컬 메모리 영역(세션 메모리 영역)

  • MySQL 서버의 클라이언트 스레드가 쿼리를 처리하는 데 사용하는 메모리 영역
  • 로컬 메모리는 각 클라이언트 스레드별로 독립적으로 할당되며 절대 공유되어 사용되지 않는다는 특징이 있다.
  • 영역
    • 커넥션 버퍼
    • 정렬 버퍼
    • 조인 버퍼
    • 바이너리 로그 캐시
    • 네트워크 버퍼

세션이 너무 많아지면 "세션별 버퍼 크기 * 세션 수"만큼의 메모리 비용이 추가로 든다.


플러그인 스토리지 엔진 모델

  • 전문 검색 엔진을 위한 검색어 파서도 플러그인 형태로 개발해서 사용 가능
  • MySQL에서 쿼리가 실행되는 과정 중 대부분의 작업은 MySQL엔진에서 처리되고, 마지막 데이터 읽기/쓰기 작업만 스토리지 엔진에 의해 처리.
    • 실질적인 GROUP BY나 ORDER BY 등 복잡한 처리는 스토리지 엔진 영역이 아닌, MySQL 엔진의 처리 영역인 쿼리 실행기에서 처리.
  • 하나의 쿼리 작업이 여러 하위 작업으로 나뉠 때, 각 작업이 MySQL 엔진 영역에서 처리되는지 아니면 스토리지 엔진 영역에서 처리되는지 구분할 줄 알아야 한다.
  • MySQL 서버에서는 스토리지 엔진뿐만 아니라 다양한 기능을 플러그인 형태로 지원한다.

 

쿼리 실행 구조

출처: Real MySQL 1권 - 그림 4.6

 

쿼리 파서

  • 사용자 요청으로 들어온 쿼리 문장을 토큰으로 분리해 트리 형태의 구조로 만들어내는 작업
  • 쿼리 문장의 기본 문법 오류는 이 과정에서 발견되어 사용자에게 오류 메시지를 전달한다.

전처리기

  • 파서 과정에서 만들어진 파서 트리를 기반으로 쿼리 문장에 구조적인 문제점이 있는지 확인
  • 내장 함수와 같은 개체를 매핑해 해당 객체 존재 여부와 객체의 접근 권한 등을 확인

옵티마이저

  • 사용자의 요청으로 들어온 쿼리 문장을 저렴한 비용으로 가장 빠르게 처리할지를 결정하는 역할

실행 엔진

  • 만들어진 계획대로 각 핸들러에게 요청해서 받은 결과를 또 다른 핸들러 요청의 입력으로 연결하는 역할을 수행

핸들러(스토리지 엔진)

  • MySQL 서버 가장 밑단에서 실행 엔진의 요청에 따라 데이터를 디스크로 저장하고 디스크로부터 읽어 오는 역할을 담당.

 

스레드 풀

  • 내부적으로 사용자의 요청을 처리하는 스레드 개수를 제한해서, 동시 처리되는 요청이 많더라도 MySQL 서버의 CPU가 제한된 개수의 처리에만 집중할 수 있게 하는 목적
  • 제한된 수의 스레드만으로 CPU가 처리하도록 적절히 유도하면 불필요한 컨텍스트 스위치를 줄여 오버헤드를 낮출 수 있다.
  • 일반적으로 CPU 코어의 개수와 스레드 그룹의 개수를 맞추는 것이 CPU 프로세서 친화도를 높이는데 좋다.
  • 스레드 그룹의 모든 스레드가 일을 처리하고 있다면 스레드 풀은 스레드 그룹에 새로운 작업 스레드를 추가할지, 아니면 기존 작업 스레드가 처리를 완료할 때까지 기다릴지 여부를 판단.

 

트랜잭션 지원 메타데이터

  • 테이블의 구조 정보와 스토어드 프로그램 등의 정보를 데이터 딕셔너리 또는 메타데이터라고 한다.
    • 기존에는 파일 기반의 메타데이터는 생성 및 변경 작업이 트랜잭션을 지원하지 않기 때문에 테이블의 생성 또는 변경 도중에 MySQL 서버가 비정성적으로 종료되면 일관되지 않은 상태로 남는 문제가 발생
  • 8.0부터는 테이블의 구조 정보나 스토어드 프로그램의 코드 관련 정보를 모두 InnoDB의 테이블에 저장하도록 개선