1. MySQL서버 구조
    1. MySQL 서버
      1. MySQL엔진
        1. 클라이언트로부터 접속 및 쿼리 요청을 처리하는 커넥션 핸들러, SQL파서, 전처리기, 쿼리의 최적화된 실행을 위한 옵티마이저가 중심
        2. 구성
          1. 커넥션 핸들러
          2. SQL 인터페이스
          3. SQL 파서
          4. SQL 옵티마이
          5. 캐시 & 버퍼
      2. 스토리지 엔진
        1. 실제 데이터를 디스크 스토리지에 저장하거나 디스크 스토리지로부터 데이터를 읽어오는 부분을 담당
        2. MySQL서버는 하나지만 스토리지 엔진을 여러개 사용 가능
        3. 구성
          1. InnoDB
          2. MyISAM
          3. Memory
        4. 다음과 같이 사용할 스토리지 엔진을 지정할 수 있음(생성시에 지정하면 이후 CRUD를 모두 해당 스토리지 엔진이 처리)
        5. CREATE TABLE test_table (fb1 INT, fb2 INT) ENGINE=INNODB;
        6. 핸들러 API
          1. MySQL 엔진의 쿼리 실행기에서 데이터를 쓰거나 읽는 경우 각 스토리지 엔진에 쓰기 또는 읽기 요청을 함
          2. 이러한 요청을 핸들러 요청이라고 하고, 여기서 사용되는 API를 핸들러 API라고함
          3. InnoDB 스토리지 엔진 또한 이 핸들러 API를 이용해 MySQL엔진과 데이터를 주고 받음
          4. SHOW GLOBAL STATUS LIKE ‘Handler%’; 명령을 통해 핸들러 API를 통한 레코드 작업 확인 가능
    2. 운영체제 하드웨어(디스크)
      1. 데이터 파일
      2. 로그 파일
  2. MySQL 스레딩 구조
    1. MySQL서버는 프로세스 기반이 아닌 스레드 기반으로 작동

    2. 포그라운드(Foreground) 스레드, 백그라운드(Background) 스레드로 구분

    3. MySQL서버에서 실행중인 스레드 목록은 다음 명령어를 통해 확인 가능

      SELECT thread_id, name, type, processlist_user, processlist_host 
      FROM performance_schema.threads ORDER BY type, thread_id;
      
    4. 많은 스레드가 나오는데 그중 thread_sql/one_connection 스레드만 실제 사용자의 요청을 처리하는 포그라운드 스레드

  3. 포그라운드 스레드(클라이언트 스레드)
    1. 최소한 MySQL서버에 접속한 클라이언트의 수만큼 존재하게됨
    2. 주로 각 클라이언트 사용자가 요청하는 쿼리 문장을 처리
    3. 클라이언트 사용자가 작업을 마치고 커넥션을 종료하면 해당 커넥션을 담당하던 스레드는 다시 스레드 캐시(Thread cache)로 돌아감
    4. 이때 이미 스레드 캐시에 일정 개수 이상의 대기 중인 스레드가 있다면, 스레드 캐시에 넣지 않고 스레드를 종료시켜 일정 개수의 스레드를 유지
    5. 이때 최대 개수는 thread_cache_size 시스템 변수를 참조
    6. 포그라운드 스레드는 데이터를 MySQL의 버퍼나 캐시로부터 가져오며, 버퍼나 캐시에 없는 경우 직접 디스크 데이터나 인덱스 파일로부터 데이터를 읽어와서 작업을 처리
    7. MyISAM 테이블은 디스크 쓰기 작업까지 포그라운드 스레드가 처리(일반적인 방식은 아님)
    8. InnoDB테이블은 데이터 버퍼나 캐시까지만 포그라운드 스레드가 처리하고, 나머지 버퍼로부터 디스크까지 기록하는 작업은 백그라운드 스레드가 처리
  4. 백그라운드 스레드
    1. MyISAM의 경우 별로 해당사항이 없고 InnoDB는 다음 작업들을 백그라운드 스레드로 처리
      1. 인서트 버퍼(insert buffer)를 병합하는 스레드
      2. 로그를 디스크로 기록하는 스레드
      3. InnoDB 버퍼 풀의 데이터를 디스크에 기록하는 스레드
      4. 데이터를 버퍼로 읽어 오는 스레드
      5. 잠금이나 데드락을 모니터링하는 메서드
    2. 위 스레드 모두 중요하지만, 그중 로그 스레드와 버퍼의 데이터를 디스크로 내려쓰는 작업을 수행하는 **쓰기 스레드(Write Thread)**임
    3. 5.5버전부터는 데이터 쓰기/읽기 스레드의 개수를 2개 이상 지정 가능해짐 innodb_write_io_threads, innodb_read_io_threads 시스템 변수로 설정 가능
    4. 데이터를 읽는 작업은 주로 포그라운드 스레드로 처리하기 때문에 읽기 스레드는 많이 설정할 필요가 없음
    5. 반면 쓰기 스레드는 많은 작업을 백그라운드 스레드를 사용하기 때문에 일반적인 내장 디스크를 사용할 때는 2~4정도
    6. DAS/SAN과 같은 스토리지를 사용하는 경우는 디스크를 최적으로 사용할 수 있을 만큼 충분히 설정하는 것이 좋음
    7. 사용자의 요청을 처리하는 도중 데이터의 쓰기 작업은 지연(버퍼링)될 수 있지만, 읽기 작업은 절대 지연될 수 없음
    8. 그래서 일반적인 DBMS에서는 대부분 쓰기 작업을 버퍼링해서 일괄 처리, InnoDB또한 이렇게 처리
    9. 하지만, MyISAM은 포그라운드 스레드가 쓰기 작업까지 함께 처리
    10. 이러한 이유로 InnoDB에서 insert, update, delete 쿼리를 실행하는 경우 디스크에 쓰기 작업이 완료될 때까지 기다리지 않아도 됨
    11. 반면 MyISAM의 경우 일반적인 insert, update, delete 쿼리는 버퍼링 기능을 사용할 수 없음
  5. 메모리 할당 및 사용 구조
    1. MySQL에서 사용되는 메모리 공간은 크게 글로벌 메모리 영역, 로컬 메모리 영역으로 구분
    2. 구분은 서버에 존재하는 많은 스레드가 공유해서 사용하는 공간인지 여부에 따라 구분
      1. 글로벌 메모리 영역
        1. 모든 메모리 공간이 MySQL서버가 시작되면서 운영체제로부터 할당
        2. 운영체제의 종류별로 다르지만, 요청된 메모리 공간을 100% 할당해줄 수 있고, 그 공간만큼 예약해두고 필요할 때 조금씩 할당해주는 경우도 있음
        3. 각 운영체제의 메모리 할당 방식은 예측이 어려움
  6. 글로벌 메모리 영역
    1. 일반적으로 포그라운드 스레드의 수와 무관하게 하나의 메모리 공간만 할당
    2. 필요에 따라 2개 이상의 메모리 공간을 받을 수도 있지만, 포그라운드 스레드의 수와는 무관
    3. 생성된 글로벌 메모리 영역이 n개이더라도 모든 스레드에 의해 공유
    4. 대표적인 글로벌 메모리 영역
      1. 테이블 캐시
      2. InnoDB 버퍼 풀
      3. InnoDB 어댑티프 해시 인덱스
      4. InnoDB 리두 로그 버퍼
  7. 로컬 메모리 영역(세션 메모리 영역)
    1. 서버상에 존재하는 포그라운드 스레드가 쿼리를 처리하는 데 사용하는 메모리 공간
    2. 대표적으로 커넥션 버퍼, 정렬(소트) 버퍼
    3. 포그라운드 스레드가 사용하는 메모리 공간이기 때문에 클라이언트 메모리 영역이라고도 함
    4. 클라이언트와 MySQL서버와의 커넥션을 세션이라고도 하기 때문에 세선 메모리 영역이라고도 함
    5. 로컬 메모리는 각 클라이언트 스레드별로 독립적으로 할당되어 절대 공유되지 않는다는 것이 특징
    6. 일반적으로 글로벌 메모리 영역의 크기는 주의해서 설정하지만, 로컬 메모리 영역은 크게 신경쓰지 않고 설정
    7. 최악의 경우(희박) MySQL서버가 메모리 부족으로 멈출수도 있으므로 적절한 메모리 공간을 설정하는 것이 중요
    8. 또한, 각 쿼리의 용도별로 필요할 때만 공간이 할당되고, 필요하지 않은 경우 MySQL이 메모리 공간 할당을 하지 않을 수도 있음(소트 버퍼, 조인 버퍼 공간이 이러한 방식)
    9. 커넥션이 열려있는 동안 계속 할당된 상태로 남아 있는 공간도 있고(커넥션 버퍼, 결과 버퍼) 이와 다르게 쿼리 실행 순간만 할당했다가 다시 해제하는 공간(소트 버퍼, 조인 버퍼)도 있음
    10. 대표적인 로컬 메모리 영역
      1. 정렬 버퍼(Sort buffer)
      2. 조인 버퍼
      3. 바이너리 로그 캐시
      4. 네트워크 버퍼
  8. 플러그인 스토리지 엔진 모델
    1. MySQL 독특한 구조 중 대표적인 것이 플러그인 모델
    2. 전문 검색 엔진을 위한 검색어 파서(인덱싱할 키워드 분리작업)도 플러그인 형태로 개발해서 사용 가능
    3. 사용자의 인증을 위한 Native Authentication, Caching SHA-2 Authentication 등도 모두 플러그인으로 구현되어 제공됨
    4. MySQL는 기본적으로 이미 많은 스토리지 엔진을 가지고 있음, 하지만 수많은 사용자 요구에 애 대해 기본적으로 제공되는 스토리지 엔진 외에 부가적인 기능을 제공하는 스토리지 엔진 필요할 수 있음
    5. 이러한 요구사항으로 다른 전문 개발 회사 또는 사용자가 직접 스토리지 엔진을 개발하는 것도 가능
    6. MySQL에서 쿼리가 실행되는 과정
    7. 핸들러
    8. 이쯤에서 그럼 MyISAM, InnoDB 스토리지 엔진 가운데 뭘 사용해도 별 차이가 없다고 생각할 수 있음
    9. 하지만, 데이터 읽기/쓰기를 통해 많이 달라질 수 있다는 것(앞선 버퍼링 부분처럼)
    10. 여기서 중요한 내용은 하나의 쿼리 작업은 여러 하위 작업으로 나뉘게 되는데, 각 하위 작업이 MySQL엔진에서 처리되는지, 스토리지 엔진에서 처리되는지 구분할 줄 알아야함
    11. SHOW ENGINES; 명령으로 서버에서 지원하는 스토리지 엔지을 볼 수 있음
    12. MySQL은 스토리지 엔진뿐만 아니라 다양한 기능을 플러그인으로 제공, 인증/전문 검색 파서/쿼리 재작성과 같은 플러그인이 있음
  9. 컴포넌트
  10. 쿼리 실행 구조