hlab-books / real-mysql-8.0-1

Real MySQL 8.0 1권
0 stars 2 forks source link

Chapter 4. 아키텍처 #1

Open hubtwork opened 4 months ago

hubtwork commented 4 months ago

Chapter Ownership @hubtwork

CHOICORE commented 4 months ago

MySQL 엔진 구성

  1. 커넥션 핸들러
    • 클라이언트 접속 및 쿼리 요청 처리
  2. SQL 파서 및 전처리기
    • SQL 문법을 파싱하고, 쿼리를 실행하기 전에 전처리
  3. 옵티마이저
    • 쿼리 실행 계획을 최적화

핸들러 API

SHOW GLOBAL STATUS LIKE 'Handler%';

위 명령으로 핸들러 API 의 작업 이력을 확인 할 수 있다.

스토리지 엔진

실제 데이터를 디스크 스토리지에 저장하거나 읽어오는 역할 수행

핸들러 API 를 만족하는 Storage Engine 을 MySQL 서버에 추가해서 사용할 수 있다.

스토리지 엔진 정의 방법

CREATE TABLE table_name (column_name column_type) ENGINE=storage_engine;

종류

  1. InnoDB Storage Engine
    CREATE TABLE table_name (column_name column_type) ENGINE=InnoDB;
  2. MyISAM Storage Engine
    CREATE TABLE table_name (column_name column_type) ENGINE=MyISAM;

사용자의 요청을 처리하는 도중 데이터의 쓰기 작업은 지연되어 처리 될 수 있지만, 데이터의 읽기 작업은 절대 지연될 수 없다. InnoDB Storage Engine 의 경우, 데이터의 쓰기 작업은 Buffer Pool 에 데이터를 쓰고, Log Buffer 에 로그를 쓴 후, Log File 에 로그를 기록한다. 이때, 데이터의 쓰기 작업이 완료되면, 클라이언트에게 완료 메시지를 전달하고, 데이터의 로그를 Log File 에 기록한다. 하지만 MyISAM Storage Engine 의 경우, 데이터의 쓰기 작업이 완료되기 전까지 클라이언트에게 완료 메시지를 전달하지 않는다. (버퍼링 기능을 사용할 수 없다.)

MySQL Thread Model

SELECT * FROM performance_schema.threads;

Foreground Thread 와 Background Thread 로 구성

  1. Foreground Thread (Client Thread)
    • 클라이언트의 요청을 처리하는 스레드
  2. Background Thread
    • MySQL 서버의 내부 작업을 처리하는 스레드
    • insert buffer merge, log flush, InnoDB flush 등의 작업을 처리
  3. Thread Pool
    • Foreground Thread 를 관리하는 스레드 풀
    • 엔터프라이즈 버전에서 사용 가능하며, Foreground Thread 가 하나씩 할당 되는 것이 아니라, 미리 정해진 개수의 스레드 풀에서 스레드를 할당 받아 사용

Client Thread 와 Foreground Thread 는 같은 의미로 사용된다.


소감

대부분의 DBMS는 읽기 성능을 챙기고 있다 정도 알고 있었지만 복구 및 장애 대응을 위한 해결 방법으로 로그, 버퍼 등을 활용하는게 인상적이었다. 이 4장에서 Pool 과 buffer size 등 성능 최적화에 필요한 키워드를 얻은 것 같다.

hubtwork commented 4 months ago

4장 요약

Overview

MySQL 서버 = MySQL 엔진 + 핸들러 API + 스토리지 엔진 핸들러 API 란 MySQL 엔진이 디스크에서 Data 를 read/write 하기 위해 명령 집합이다. 스토리지 엔진은 핸들러 API 를 구현함으로서 Query Excutor 에게 읽기/쓰기 연산을 제공한다. 반면 그 외의 Data 를 정렬하거나 그룹핑 하는 등의 동작은 스토리지 엔진이 아닌 MySQL 엔진의 Query Excutor 에서 실행된다.

플러그인, 컴포넌트와 같은 Add-On 개념도 있는데 이는 Application 개발자가 알 필요 없어 보임.

MySQL 엔진 Thread 기반으로 동작하며 Foreground 는 사용자 요청을 처리하는 데에 쓰이며, Background 는 Log Thread, Write Thread 와 같이 주어진 역할을 수행하는 스레드들이 존재한다.

쓰기 작업을 매번 수행하면 부하가 생기기 때문에 버퍼를 이용한 쓰기 지연 동작 등을 수행한다. ( Write Thread ) (주의) 읽기 지연은 존재하지 않는다.

메모리 유형

Query 실행 구조

  1. Query Parser : Query 요청을 Tokenizing 해 트리 구조로 재해석 ( Syntax Error 검증 )
  2. Preprocessor : Parser Tree 를 검증해 실행 이전에 검증 ( Table, Column 존재 여부, 권한 확인 등 )
  3. Optimizer - Query 를 더 효율적으로 실행하기 위한 실행 계획 수립
  4. Executor - 실행 계획에 따라 각 핸들러 요청을 유기적으로 처리

DB Metadata 의 경우 File 기반으로 관리하고 있었는데, 이 경우 File 수정 중 MySQL 서버 비정상 종료에 따른 일부 변경만 반영되는 등의 문제가 발생한다. 이에 8.0 부터는 InnoDB 의 테이블에 트랜잭션 기반으로 저장하도록 변경해 일관성이 깨지는 문제를 해결한다.


InnoDB Architecture

Record 기반 Lock 제공을 통해 높은 동시성 처리 능력 및 안정성이 특징인 스토리지 엔진 MyISAM 과 다르게 PK ClusteringForeign Key 를 지원한다. PK 값의 순서대로 Clustering ( 군집화 ) 되어 디스크에 저장되며, 이에 따라 Range Scan 에 유리하고 여타 보조 인덱스에 비해 Optimizer 에 의해 선정될 확률이 높다.

운영 환경에서 FK 를 잘 쓰지 않는 이유 장애가 발생하거나, 데이터 조작이 필요한 경우 Constraints 에 의한 지연이 생길 수 있다. 또한 FK 의 부모/자식 테이블 모두 FK 로 쓰이는 컬럼에 Index 가 생성되므로 새로운 FK 제약 조건의 테이블 생성 시 확인을 위한 Lock 이 부모 테이블 전체에 전파될 수 있다. 이러한 이유로 DeadLock 문제에서 안전하지 않으므로 권장되지 않는다. 추가적으로 자동 데드락 감지 ( Wait-for List 검사 스레드 + 스케줄링 ) 및 장애 복구 자동화 ( 실패한 트랜잭션 및 Partial write 등을 자동으로 복구 ) 와 같은 각종 운영 편의 기능을 제공한다.

MVCC ( Multi Version Concurrency Control )

InnoDB Buffer Pool

성능 향상을 위해 디스크의 Data 나 Index 정보를 메모리에 캐시 + 쓰기 지연 기능을 지원하기 위한 버퍼를 제공한다. 기존에는 단일로만 제공되어 전체 Semaphore 에 의해 잠금 경합이 일어나는 경우가 많았는데, 8.0 부터는 경합 분산이 가능하도록 여러 개의 작은 버퍼 풀로 나누어 관리하는 방식 또한 지원한다.

용어 정리 Clean Page : 디스크로부터 읽어 버퍼에 저장된 후 아직 변경이 일어나지 않은 페이지 Dirty Page : 새로 생성하거나 디스크로부터 읽은 후 데이터가 변경된 페이지

구성 : 메모리 상의 데이터 페이지 기반 버퍼

Buffer Flush 5.7~ 부터는 Flush 동작에 의한 성능 저하를 막기 위해 2가지 Flush 를 백그라운드로 수행한다. 더불어 일정 비율 이상의 더티 페이지가 발생할 시, Disk IO Burst 방지를 위해 조금씩 디스크에 동기화시키는 작업을 수행한다.

  1. Flush_list flush - 주기적으로 Flush List 의 오래된 페이지부터 디스크에 동기화
  2. LRU_list flush - 주기적으로 LRU List 를 스캔해 가장 오래전에 hit 된 페이지부터 디스크에 동기화

    Adaptive Flush - flush 효율 증대를 위해 Redo Log 의 증가 속도를 분석해 적정 수준의 Dirty Page 만 존재하도록 간헐적으로 디스크 동기화 작업 수행

Redo Log

Undo Log

Adaptive Hash Index


MyISAM 스토리지 엔진

MySQL 로그

hubtwork commented 4 months ago

소감

MySQL 사용 중 InnoDB 로 넘어오면서 생긴 특징 중 특정 키워드들의 경우에 대해서만 부분적으로 공부했었음. ( 아래 표기 )

근데 아키텍처 전반적으로 보면서 캐시/버퍼를 적재적소에 배치하고 Develop 해온 과정을 확인하니 머리가 좀 어질어질 하긴 하다. 특히 버퍼 풀을 백분 활용하기 위한 Undo/Redo Log 의 활용 방안 및 스토리지 엔진 레벨의 지연 쓰기 의 구성을 신기하고 재밌게 봄.

근데, 아마 모든 챕터 중 이 챕터가 제일 심할 것 같은데 시스템 레벨에서 해당 로그들의 현재 상황, 버퍼의 상황 등을 직접 조회하는 Query 들은 그냥 볼 수는 있구나 하고 넘김. 애플리케이션 개발자로서 업무를 진행하면서 저런 디테일한 분석을 위한 테이블 스페이스/버퍼 조회를 할 일은 아예 없다고 생각함.

전반적으로 당연하게 생각했던 MySQL 이 가진 특징들이 이런 원리로 돌아가는 구나 정도로 보기엔 좋은 챕터였고, 대충 키워드 별로 그 특징 및 동작 원리 등만 좀 기억하고 넘길 예정임. ( 뭐 필요하면 다시 찾아보겠지 ㅋㅋㅋ 근데 필요할 일이 있을까 ) 실무에서 이 각 세부 스토리지 엔진의 구성요소에 대해 분석하거나 할 일은 없을 것 같음.

차라리 각종 DB 로그 관련된 설정 등은 Fault 나 Outlier 가 발생했을 때 조회해서 확인해볼 내용들이 있을 것 같아 그땐 잠깐 책 열어 보거나 인터넷 검색하기.. ( 그냥 볼 수 있구나 정도로 알고 넘어가련다 )

다시는 보지 말자.

zinokim commented 4 months ago

MySQL 서버 아키텍처

스레드 기반으로 작동

글로벌 메모리

InnoDB 스토리지 엔진 아키텍처

MYSQL 비정상 작동 및 종료에 대한 기술적 대응


소감

MySQL 서버에 대해 구조적, 기술적으로 알게 되어 흥미로웠다. 평소 DB에 대한 기술적 대화에서 언급되었던 MVCC, 언두 로그 등의 개념이 어떤 것인지 보다 자세히 이해할 수 있었다. 특히 MVCC, 언두 로그, 리두 로그 등 비정상 작동 및 종료에 대한 MySQL에서의 기술적 대응이 조금 놀라웠다. MySQL 5.5 / 5.7 그리고 8.0에 대해 의문을 갖지 않고 사용했던 과거의 내가 부끄러워지는 시간이었다. 게다가 책을 읽고 요약하는 것을 너무 오랫동안 하지 않아서 요약을 제대로 하지 못하고 있는 점이 아쉽다. 개인적으로 면접을 준비한다면 한 번은 꼭 봐야할 내용들이 있는 챕터라고 생각이 들었다.

KangHun-Lee commented 4 months ago

느낀 점

  1. MySQL 의 전반적인 아키텍처 구성을 살펴 볼 수 있어서 좋았다.
  2. 과연 실무에서 아키텍처 레벨을 언급하면서 이야기하는 빈도 수가 얼마나 될까...?

    그냥 참고만 하고 필요시 다시 찾아보자 & 인터뷰시 한번 더 보자..

  3. 개인적으로 이 챕터에서 중요하다고 생각 되는 부분은 하기에 표시함
    • InnoDB
    • Redo & Undo
    • 슬로우 쿼리 로그
  4. 이번 챕터 오너는 과연 MyISAM 을 정리할까? 라는 생각이 있었음(역시나..)
  5. 북 스터디 진행의 이런 방식은 처음인데 생각보다 좋고 이렇게 느낀 점을 쓰는게 맞는건가... 챕터 내용에 비해 너무 적은듯한.. 이건 이야기 해 볼 필요가 있을듯...