[Real MySQL 8.0] 4장 리뷰

2026. 7. 7. 00:59·Dev Book Review/Real MySQL
728x90

 

 

MySQL 서버는 크게 MySQL 엔진과 스토리지 엔진으로 구분할 수 있다.

 

  • MySQL 엔진
    • 커넥션 핸들러
    • SQL 파서, 전처리기
    • 옵티마이저
    • 쿼리 실행기
  • 스토리지 엔진
    • 요청된 SQL 문장을 분석하거나 최적화 하는 등 DBMS의 뇌에 해당하는 처리를 수행한다.
    • 대표적인 예시로 InnoDB, MyISAM이 있다.

핸들러 요청 : MySQL 엔진의 쿼리 실행기에서 데이터를 쓰거나 읽어야할 때 스토리지 엔진에 쓰기 또는 읽기를 요청하는것이다.

 

Foreground thread, Background thread

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

 

Foreground thread

MySQL 서버에 접속된 클라이언트 수만큼 존재하며 주로 각 클라이언트 사용자가 요청하는 쿼리 문장을 처리한다.

만약 클라이언트 사용자가 작업을 마치고 커넥션을 종료하면 해당 스레드는 다시 스래드 캐시로 되돌아간다.

 

스레드 캐시에 존재할 수 있는 최대 스레드 개수는 thread_cache_size로 할당할 수 있다.

대부분 읽기 작업(Select)에서 포그라운드 스레드가 사용이된다.

 

Background thread

대표적으로 스토리지 엔진을 사용하는 InnoDB의 경우 5가지 사항이 백그라운드로 처리된다.

 

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

데이터를 쓰는 작업(Update, Insert)에서 대부분 백그라운드 스레드가 사용된다.

 

메모리 영역

MySQL에서 사용하는 메모리 공간은 크게 글로벌 메모리 영역, 로컬 메모리 영역으로 나누어 진다.

 

  • 글로벌 메모리
    • MySQL서버가 시작되면서 운영체제로부터 할당되며 종료될때 해제된다.
    • 클라이언트 스레드의 수와 무관하게 하나의 메모리 공간만 할당된다.
    • MySQL 서버 내부의 모든 스레드가 공유한다.
    • ex) InnoDB 버퍼 풀, 테이블 캐시, 로그 버퍼 등
  • 로컬 메모리
    • MySQL 서버상에 존재하는 클라이언트 스레드가 쿼리를 처리하는데 사용된다.
    • 각 클라이언트 스레드가 독립적으로 할당되며 공유하지 않는다.
    • 클라이언트 스레드가 쿼리를 실행할때 필요에 따라 할당이 된다.
    • ex) 정렬 버퍼, 조인 버퍼, 바이너리 로그 캐시 등

 

플러그인, 컴포넌트

기존 MySQL은 플러그인 방식을 사용하였다. 하지만 8.0버전부터 플러그인 단점으로 인해 컴포넌트 방식을 사용하게 된다.

 

플러그인의 단점으로는 오직 MySQL 엔진과 직접 연결할 수 밖에 없고 플러그인끼리는 통신이 불가하였다. 따라서 2개의 플러그인을 동시에 같이 사용하려고 해도 통신이 안되 직접 엔진 소스 코드를 수정할 수 밖에 없었다.

 

이러한 단점을 해결하기 위해 컴포넌트가 등장하였으며 컴포넌트끼리, 엔진과 자유롭게 연결 가능하며 서비스를 주고받을 수 있도록 가능하게 하였다.

 

쿼리 실행 구조

 

 

MySQL은 위 사진과 같이 쿼리를 실행할때 해당 구조로 동작한다.

 

쿼리 파서

사용자 요청으로 들어온 쿼리 문장을 토큰으로 분해해 트리 행태로 만들어 기본 문법이 오류가 있는지 확인하여 사용자에게 전달한다.

 

전처리기

쿼리 파서 과정 이후 파서 트리를 기반으로 쿼리 문장에 구조적인 문제점(테이블이 존재하는지, 컬럼이 있는지 등)이 있는지 확인한다. 또한 권한상 사용할 수 없는 경우 해당 단계에서 오류를 처리하여 사용자에게 전달한다.

 

옵티마이저

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

 

실행 엔진

핸들러(InnoDB 스토리지 엔진, MyISAM)에 명령을 내리고 그에 대한 결과를 받아서 조합하는 역할을 한다. -> 만들어진 계획대로 각 핸들러에게 요청하여 받은 결과를 또다른 핸들러 요청의 입력으로 연결한다.

 

핸들러(스토리지 엔진)

MySQL 실헹 엔진의 요청에 따라 데이터를 디스크로 저장하고 읽어오는 역할을 담당한다. 즉 핸들러는 스토리지 엔진이며 사용하는 엔진에 따라 핸들러도 달라진다.

 

쿼리 캐시

SQL의 실행 결과를 메모리에 캐시하고 동일 SQL 쿼리가 실행되면 테이블을 읽지 않고 즉시 결과를 반환하기에 매우 좋은 성능을 가진다 하지만 테이블의 데이터가 변경, 삭제되는 경우 그에 대한 캐시값도 삭제되어야 하며 이는 심각한 동시 처리 성능 저하를 유발한다. 이후

8.0으로 올라오며 기능이 완전히 삭제되었다.

 

스레드 풀

기존 OS 관점에서 보면 사용자가 요청을 날리면 서버는 새로운 스레드를 생성하고 결과를 반환하고 요청이 없으면 스레드를 삭제한다 이때 OS는 스레드를 생성하고 삭제하는 비용이 엄청나게 커진다 따라서 스레드 풀을 도입하여 미리 생성한 풀에 사용자의 요청에 응답한 후 스레드를 제거하지 않고 풀에 계속 대기하는 방식이다.

 

그렇다고 스레드 풀이 많으면 좋은가? 그건 아니다 왜냐하면 스레드도 마찬가지로 컨텍스트 스위칭(cpu가 스레드를 점유하는데 하나씩 점유)이 자주 발생하면 스레드 전환하는데만 오랜 시간을 쏟는다.

 

Percona Server의 스레드 풀 기능은 선순위 후순위 큐를 사용하여 쿼리를 우선적으로 처리할 수 있는 기능을 제공한다.

-> 트랜잭션내에 속한 SQL을 빨리 처라히면 트랜잭션 잠금이 빨리 해제되고 경합을 낮춰 전체적인 처리 성능이 높아진다.

 

InnoDB는 유일하게 레코드 기반의 잠금을 제공하며 그 때문에 높은 동시성 처리가 가능하다.

 

Primary Key에 의한 클러스터링

InnoDB의 모든 테이블은 프라이머리키를 기준으로 클러스터링되어 저장된다. 즉 pk 값 순서대로 디스크에 저장된다. 모든 세컨더리 인덱스는 레코드 주소 대신 pk의 값을 논리적 주소로 사용한다.

 

BUT MyISAM 스토리지 엔진에서는 클러스터링 키를 지원하지 않는다. MyISAM 테이블의 PK키를 포함한 모든 인덱스는 물리적 레코드 주소 값(rowID)를 가진다. 또한 외래키는 서버 운영에 불편함이 있어서 사용되지 않는다.

 

외래키는 innoDB에서 지원하는 기능으로 MyISAM memory 테이블에서는 사용하지 않는다. InnoDB에서 외래키는 부모테이블과 자식테이블 모두 해당 컬럼에 인덱스 생성이 필요하다.

변경시 부모 테이블이나 자식 테이블에 데이터가 있는지 체크해야하며 잠금이 여러 테이블로 전파되고 데드락이 발생할 수 있다.

 

MVCC(Multi-Version Concurrency Control) 다중 버전 동시성 제어

레코드 레벨의 트랜잭션을 동시에 지원하는 DBMS가 제공하는 기능으로 MVCC는 잠금을 사용하지 않는 일관된 읽기를 제공한다. InnoDB는 언두 로그를 사용해 구현한다.

 

InnoDB는 MVCC 기술을 이요해 잠금을 걸지 않고 읽기 작업을 수행한다. 잠금을 걸지 않기에 읽기 작업을 다른 트랜잭션이 가지는 잠금을 기다리지 않고 읽기 작업이 가능하다.

즉 다른 사용자가 레코드를 변경하고 아직 커밋을 하지 않았다 하더라도 변경 트랜잭션이 다른 사용자의 select 작업을 방해하지 않는다.

→ 변경되기 전 언두 로그를 읽어온다.

 

자동 데드락 감지

InnoDB 스토리지 엔진은 잠금이 교착 상태에 빠지진 않았는지 체크하기 위해 잠금 대기 목록을 그래프 형태로 관리한다. 또한 데드락 감지 스레드가 있어 주기적으로 대기 그래프를 검사해 트랜잭션을 종료한다.

 

자동화된 장애 복구

InnoDB에는 손실이나 장애로부터 데이터를 보호하기 위한 여러가지 메커니즘이 탑재되어 있다.

 

버퍼 풀

디스크 데이터 파일이나 인덱스 정보를 메모리에 캐시해두는 공간이다 또한 쓰기 작업을 지연시켜 일괄 작업으로 처리도 해준다. Insert, Update, Delete 처럼 데이터를 변경하는 쿼리는 파일의 분산되어있는 레코드를 변경하기에 랜덤한 디스크 작업을 발생시킴

 

버퍼풀 구조

InnoDB 스토리지 엔진은 버퍼 풀이라는 공간을 거대한 메모리 공간을 페이지 크기의 조각으로 쪼개어 InnoDB 스토리지 엔진이 데이터를 필요로 할때 해당 데이터 페이지를 읽어 각 조각에 저장한다.

 

  • LRU 리스트 : 한쪽은 MRU(최근 사용), 한쪽은 LRU(사용하지 않은) 자주 쓰는 데이터는 남기고 최근에 안쓴 데이터부터 메모리에서 삭제한다.
  • 플러시 리스트 : 디스크와 내용이 달라진 페이지를 모아서 순서대로 저장한다.
  • 프리 리스트 : 버퍼풀에서 채워지지 않는 비어있는 페이지 목록이다.

 

버퍼 풀과 리두 로그

InnoDB 버퍼 풀은 데이터베이스 성능 향상을 위해 데이터 캐시, 쓰기 버퍼링이라는 용도가 있어 버퍼풀의 메모리 공간만 늘리면 캐시 기능만 향상된다. 

→ 단순히 버퍼 풀만 늘린다고 버퍼풀 쓰기 기능은 향상 되지 않고 읽기 기능만 향상된다.

 

  • 클린 페이지 : 디스크에서 읽고 전혀 변경 되지 않는 페이지
  • 더티 페이지 : 페이지는 디스크와 메모리(버퍼 풀)의 데이터 상태가 다르기 때문에 언젠가는 디스크로 기록되어야 하는 페이지
  • 리두 로그 : 리두 로그 파일에서 재사용 불가능한 공간이다.

InnoDB 스토리지 엔진에서 리두 로그는 1개 이상의 고정 크기 파일을 연결해 순환고리로 사용한다

→ 하나의 로그파일을 끝까지 다 사용해도 처음부터 덮어씌워 로그 엔트리(단순한 데이터 변경만 있지 않고 서버가 꺼져도 복구 가능한 데이터를 포함)로 다시 작성한다.

 

  • LSN : 리두 로그 파일은 기록될 때마다 로그 포지션이 제일 중요하다.

 

스토리지 엔진은 주기적으로 체크포인트를 발생시켜 리두 로그와 버퍼풀의 더티페이지를 디스크로 동기화한다. 이때 시작점은 최근 체크포인트점의 LSN이 되며 끝점은 리두 로그 엔트리로 값이 계속 증가한다.

 

이때 체크포인트 에이지는 마지막 리두 로그 엔트리 LSN 값에서 최근 체크포인트 LSN을 빼면 현재 활성 리두 로그의 정도를 알 수 있다.

 

버퍼 풀 플러시

더티 페이지들은 어떤 방식으로 디스크에 반영하는지에 대한 내용이며 이때 2가지 방법을 사용해서 반영한다.

 

플러시 리스트 플러시

데이터의 안전한 영구 저장을 하며 그에 대한 리두로그 공간을 확보하기 위한 방법으로 주기적으로 플러시리스트의 플러시 함수를 호출해 플러시 리스트에서 오래전에 변경된 데이터 페이지 순서대로 디스크에 동기화 작업 수행

 

이때 스토리지 엔진에서 더티 페이지를 디스크로 동기화하는 스레드를 클리너 스레드라 한다.

 

LRU 리스트 플러시

새로운 데이터를 읽어올 빈 메모리 공간을 확보하기 위해 LRU 플러시 함수가 사용된다. LRU 리스트의 끝부분부터 시작해서 페이지를 스캔하며 더티 페이지는 디스크에 동기화하게 하며 클린 페이지는 프리페이지로 옮긴다.

728x90
저작자표시 (새창열림)

'Dev Book Review > Real MySQL' 카테고리의 다른 글

[Real MySQL 8.0] 1 ~ 3장 리뷰  (0) 2026.07.02
'Dev Book Review/Real MySQL' 카테고리의 다른 글
  • [Real MySQL 8.0] 1 ~ 3장 리뷰
쿨쿨.
쿨쿨.
  • 쿨쿨.
    All of the life
    쿨쿨.
  • 전체
    오늘
    어제
    • 분류 전체보기 (278)
      • Programming (47)
        • C, C++ (18)
        • Python (6)
        • Java (1)
        • HTML,CSS,JS (3)
        • SQL(DB) (13)
        • SpringBoot (3)
        • Android (2)
        • CI,CD (1)
      • Algorithm (173)
        • Review (4)
      • Security (14)
        • WebHacking (3)
        • Websecurity (11)
      • OS (19)
        • Linux (12)
        • Mac os (2)
      • 머신러닝 (1)
      • CS(Computer Science) (12)
        • 컴퓨터 네트워크 (3)
        • 컴퓨터 구조 (1)
        • 인공지능 (8)
      • Docker (1)
      • Dev Book Review (3)
        • Clean Code (1)
        • Effective Java (0)
        • Real MySQL (2)
      • SWM (1)
      • Review (5)
      • AWS (2)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    linux
    트리
    WebSecurity
    시뮬레이션
    c언어
    정렬
    다이나믹 프로그래밍
    BFS
    재귀
    Leviathan
    브루트포스
    DP
    투포인터
    wargame
    누적합
    에라토스테네스의 체
    DFS
    우선순위 큐
    그리디
    구현
    다익스트라
    코딩
    그래프 이론
    Bandit
    이분탐색
    깊이우선탐색
    비트마스킹
    우선순위큐
    백준
    백트래킹
  • 최근 댓글

  • 최근 글

  • 250x250
  • hELLO· Designed By정상우.v4.10.6
쿨쿨.
[Real MySQL 8.0] 4장 리뷰
상단으로

티스토리툴바