도서/Real My SQL

[Real My SQL] MySQL 엔진 아키텍처 - 2

k0o9 2022. 11. 1. 02:17

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

MySQL의 독특한 구조 중 하나는 플러그인 모델이다.

플러그인에는 스토리지 엔진 뿐만 아니라 다양한 부가기능들을 제공한다.

 

MySQL에서 쿼리가 실행되는 과정을 크게 나누면 다음과 같다.

  1. SQL 파서
  2. SQL 옵티마이저
  3. SQL 실행기
  4. 데이터 읽기 / 쓰기

1 ~ 3 까지의 작업은 SQL 엔진의 영역에서 처리되며 4의 작업만 스토리지 엔진 모델에서 처리된다.

즉 사용자가 새로운 스토리지 엔진을 만든다고 하더라도 데이터 DBMS의 전체 기능이 아닌 읽기 /쓰기 기능만 수행하는 엔진을 만들게 된다. 즉 MyISAM을 사용하나 InnoDB를 사용하나 데이터 읽기 / 쓰기 작업에서만 차이가 있다는 것이다.

 

MySQL 엔진은 스토리지 엔진을 조정하기 위해 핸들러라는 것을 사용한다

 

핸들러

  • MySQL 엔진이 각 스토리지 엔진에게 데이터를 읽어오거나 저장하도록 명령하려면 핸들러를 통해야 한다.
  • 'Handler_'로 시작하는 상태변수는 MySQL엔진이 각 스토리지 엔진에게 보낸 명령의 횟수를 의미하는 변수이다.

MySQL 서버에 포함되지 않은 스토리지 엔진을 사용하려면 서버를 다시 빌드해야한다. 하지만 플러그인 형태로 빌드된 스트리지 엔진 라이브러리를 다운로드한다면 손쉽게 스토리지 엔진을 업그레이드 할 수 있다.

 

컴포넌트

MySQL 8.0 부터는 기존의 플러그인 아키텍처를 대체하기 위해 컴포넌트 아키텍처를 지원한다.

컴포넌트는 다음과 같은 플러그인의 단점을 보완한다.

  • 플러그인은 오직 MySQL 서버와 인터페이스 할 수 있고, 플러그인들끼리는 통신할 수 없다.
  • 플러그인은 MySQL 서버의 변수나 함수를 직접 호출하기 때문에 캡슐화가 되지 않아서 안전하지 않다.
  • 플러그인은 상호 의존 관계를 설정할 수 없어서 초기화가 어렵다.

쿼리 실행 구조

쿼리 실행 구조

  1. 쿼리파서
    • 사용자 요청으로 들어온 쿼리 문장을 토큰으로 분리해서 트리 구조로 만들어내는 작업을 의미한다.
    • 기본 문법 오류가 이 과정에서 발견되고 사용자에게 에러 메세지를 전달한다.
  2. 전처리기
    • 쿼리 파서에서 만들어진 트리를 기반으로 쿼리의 구조적인 문제점이 있는지 확인한다.
    • 각 토큰을 각각의 개체에 매핑해 해당 객체의 존재 여부, 접근 권한 등을 확인한다.
    • 실제 존재하지 않거나 권한상 사용할 수 없는 개체의 토큰은 이 단계에서 걸러진다.
  3. 옵티마이저
    • 사용자의 요청으로 들어온 쿼리를 저렴한 비용으로 가장 빠르게 처리할지를 결정한다.
    • 두뇌 역할(회사 경영진)
  4. 실행 엔진
    • 만들어진 계획대로 각 핸들러에게 요청하는 역할을 한다.
    • 이 때 핸들러에 요청한 결과값을 다시 다른 핸들러에 요청하는 역할 또한 수행한다. 
    • 손과 발의 역할(중간 관리자)
  5. 핸들러(스토리지 엔진)
    • 가장 말단에서 MySQL 실행 엔진의 요청에 따라 데이터를 디스크로 저장하고 디스크로부터 읽어오는 역할을 담당한다.
    • 즉 스토리지 엔진을 의미하며 MyISAM 테이블을 조작할때는 핸들러가 MyIsam이 되고 InnoDB를 조작할때는 핸들러가 InnoDB가 된다.

 

쿼리 캐시

MySQL 서버에서 쿼리 캐시는 빠른 응답을 필요로 하는 웹 기반 프로그램에서 매우 중요한 역할을 담당했다.

하지만 쿼리 캐시는 테이블의 데이터가 변경되면 캐시에 저장된 관련 데이터를 삭제했다. 이능 심각한 성능저하를 유발하였고 MySQL 8.0이 되면서 삭제 되었다.

MySQL의 쿼리 캐시는 데이터 변경은 거의 없고 읽기만 하는 환경에서는 훌륭한 기능이지만 이런 조건을 가진 서비스는 드물었고 결국 삭제되었다.

 

스레드 풀

MySQL 엔터프라이즈 에디션에서만 제공한다.

MySQL의 스레드풀은 서버 프로그램에 내장돼 있지만 Percona Server의 스레드 풀은 플러그인 형태로 작동하게 구현돼 있다.

따라서 MySQL 커뮤니티 에디션에서도 스레드풀을 사용하고 싶다면 동일 버전의 Persona Server에서 스레드풀 플러그인 라이브러리를 설치하면 된다.

 

  • 내부적으로 사용자 요청 스레드 개수를 줄여서 MySQL 서버의 CPU가 제한된 개수의 스레드 처리에만 집중할 수 있게 해서 서버의 자원 소모를 줄이는 것이 목적이다.
  • 실제 서비스에서 눈에 띄는 성능 향상을 보여준 경우는 드물다.
  • 스케줄링 과정에서 CPU 시간을 제대로 확보하지 못하면 쿼리 처리가 더 느려지는 사례도 있다.
  • 제한된 수의 스레드만으로 CPU가 잘 처리하도록 유도한다면 불필요한 컨텍스트 스위치를 줄여서 오버헤드를 낮출 수 있다.
  • Percona Server의 스레드 풀은 CPU 코어의 개수만큼 스레드 그룹을 생성한다.
    • thread_pool_size로 조정할 수 있다.
    • 일반적으로는 CPU 코어의 개수와 맞추는 것이 CPU 프로세서 친화도를 높이는데 좋다.
  • MySQL 서버가 처리해야할 요청이 생기면 스레드 풀로 처리를 이관한다.
  • 이 때 이미 스레드 풀에 이미 처리 중안 작업이 있는 경우 thread_pool_oversubscribe 시스템 변수에 설정된 개수만큼 추가로 더 받아들여서 처리한다.
    • 이 값이 너무 클 경우 스케줄링 해야할 스레드가 많아져 스레드 풀이 비효율적이게 된다.
  • 스레드 그룹의 모든 스레드가 일을 처리하고 있다면 스레드 풀은 스레드를 추가할지 아니면 기다릴지를 판단한다.
    • 스레드 풀의 타이머 스레드는 주기적으로 스레드 그룹의 상태를 체크해서 thread_pool_stall_limit 시스템 변수에 정의된 시간만큼 작업스레드가 처리중인 작업을 완료못하면 새로운 스레드를 스레드 그룹에 추가한다.
    • 이 때 전체 스레드의 개수는 thread_pool_max_threads를 넘을 수 없다.
    • 즉 스레드가 각자 작업을 처리하는 동안 새로운 요청이 들어와도 스레드는 thread_pool_stall_limit 만큼 기다려야 새로운 요청을 처리할 수 있다

Percona Server의 스레드 풀 플러그인은 선순위 큐와 후순위 큐를 이용해 특정 트랜잭션이나 쿼리를 먼저 처리하는 기능도 제공한다. 이렇게 먼저 시작된 트랜잭션을 처리해주면 해당 트랜잭션이 가지고 있던 잠금이 빨리 해제되서 전체적인 처리 성능을 향상시킨다.

 

트랜잭션 지원 메타데이터

  • DB 서버에서 테이블의 구조 정보, 스토어드 프로그램 등의 정보를 데이터 딕셔너리 또는 메타 데이터라고 한다.
  • MySQL 5.7 까지 테이블 구조를 FRM 파일에 저장하고 일부 스토어드 프로그램 또한 파일 기반으로 관리했다. 하지만 파일 기반의 메타데이터는 생성 및 변경 작업이 트랜잭션을 지원하지 않아서 여러 문제가 있었다.
  • MySQL 8.0 부터는 이러한 문제를 해결하기 위해 테이블 구조 정보, 스토어드 프로그램의 코드 관련 정보를 InnoDB의 테이블에 저장하도록 개선했다.
  • MySQL서버가 작동하는데 기본으로 필요한 테이블을 묶어서 시스템 테이블이라고 한다. 이러한 시스템 테이블을  MySQL 8.0부터는 InnoDB스토리지 엔진을 사용하도록 개선했다.
  • 시스템 테이블과 딕셔너리 정보를 모두 모아서 mysql DB에 저장하고 mysql DB는 통째로 mysql.ibd라는 테이블 스페이스에 저장된다.
  • 따라서 MySQL 서버의 데이터 디렉터리에 존재하는 mysql.ibd라는 파일은 다른 *.ibd파일과 특별히 주의해야한다.
  • MySQL 8.0 부터 데이터 딕셔너리와 시스템 테이블이 모두 트랜잭션 기반의 InnoDB 스토리지 엔진에 저장되도록 개선하면서 기존의 파일 기반 메타데이터를 사용할 때의 문제점을 개선했다.
  • 하지만 MyISAM이나 CSV와 같은 스토리지 엔진의 메타 정보는 여전히 저장할 공간이 필요했다.
  • MySQL은 InnoDb 이외의 스토리지 엔진을 사용하는 테이블들을 위한 SDI파일을 사용한다.
    • SDI는 직렬화를 위한 포맷으로 InnoDB 테이블들도 SDI파일로 변환할 수 있다.