Programming/Database

Real MySQL - 엔진 2

긍정왕웹서퍼 2023. 7. 23. 21:36
728x90

메모리 할당 및 사용 구조

MySQL 메모리 사용 및 할당 구조

MySQL 에서 메모리는 크게 두가지로 구분된다. 글로벌 메모리 영역과 로컬 메모리 영역으로 구분되며 글로벌 메모리 영역의 모든 메모리는 MySQL서버가 시작되면서 운영체제로부터 할당된다.

 

MySQL 메모리 사용 및 할당 구조

 

 

글로벌 메모리 영역

일반적으로 하나의 메모리 공간만 할당되며 필요에 따라 2개 이상의 메모리 공간이 할당받을 수 있지만 클라이언트의 수와 무관하며 생성된 글로벌 영역은 모든 스레드에 의해 공유된다. 글로벌 메모리 영역에 종류는

  • 테이블 캐시
  • InnoDB 버퍼 풀
  • InnoDB 어댑티브 해시 인덱스
  • InnoDB 리두 로그 버퍼

 

로컬 메모리 영역

세션 메모리 영역이라고도 표현하며 클라이언트 스레드가 쿼리를 처리하는 데 사용하는 메모리 영역이다. 클라이언트 커넥션으로부터 요청을 처리하기 위해 스레드를 할당하게 되며 이 때 할당되는 메모리 공간이라고 해서 클라이언트 메모리 영역이라고도 한다.

로컬 메모리는 각 클라이언트 스레드별로 독립적으로 할당되며 절대 공유되지 않는다는 특징이 있다. 또한 각 쿼리의 용도별로 필요할 때만 공간이 할당되고 필요하지 않은 경우에는 MySQL이 메모리 공간을 할당조차 하지 않을 수 있다는 점이다. 대표적으로 정렬 버퍼와 조인 버퍼가 그러하다. 로컬 메모리 공간은 커넥션이 열려있는 동안 계속 할당된 상태로 남아 있는 공간도 있고 그렇지 않고 실행하는 순간에만 할당했다가 다시 해제하는 공간도 있다.

  • 정렬 버퍼
  • 조인 버퍼
  • 바이너리 로그 캐시
  • 네트워크 버퍼

 

 

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

MySQL의 독특한 구조 중 대표적인 것인 플러그인 모델이다. 전문 검색 엔진을 위한 검색어 파서도 플러그인 형태로 개발해서 사용가능하며, 사용자 인증을 위한 Auth관련 플러그인들도 있다. 그리고 MySQL 쿼리가 실행되는 과정을 살펴보면 대부분의 작업이 MySQL엔진에서 처리되고, 마지막 ‘데이터 읽기/쓰기’ 작업만 스토리지 엔진에 의해 처리된다.

MySQL에서 핸들러(Handler)란 자동차로 비유하자면 사람이 핸들을 이용해 자동차를 운전하듯 프로그래밍 언어에서 어떤 기능을 호출하기 위해 사용하는 운전대와 같은 역할을 하는 객체를 의미하며, MySQL 엔진이 사람역할이고, 각 스토리지 엔진이 자동차 역할을 하는데 여기서 스토리지 엔진을 조정하기 위해 핸들러가 사용된다.

하나의 쿼리 작업은 여러 하위 작업으로 나뉘는데, 각 하위 작업이 MySQL 엔진 영역에서 처리되는지 아니면 스토리지 엔진 영역에서 처리되는지 구분할 줄 알아야 한다.

 

 

컴포넌트

8버전부터는 기존의 플러그인 아키텍처를 대체하기 위해 컴포넌트 아키텍처가 지원된다.

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

 

 

쿼리 실행 구조

쿼리 실행 구조

 

  1. 쿼리 파서 사용자 요청으로 들어온 쿼리 문장을 토큰(MySQL이 인식할 수 있는 최소 단위의 어휘나 기호)으로 분리해 트리 형태의 구조로 만들어 내는 작업을 의미하며 쿼리 문장의 기본 문법 오류는 이과정에서 발견된다.
  2. 전처리기 파서 과정에서 만들어진 트리를 기반으로 쿼리 문장에 구조적 문제점이 있는지 확인하며, 각 토큰을 테이블 이름이나 컬럼 이름, 내장 함수등 개체를 매핑해 해당 객체의 존재 여부와 객체의 접근 권한등을 확인하는 과정을 거친다.
  3. 옵티마이저 옵티마이저가 두뇌라면 실행 엔진과 핸들러는 손과 발에 비유할 수 있다. 실행 엔진이 하는 일을 더 쉽게 이해할 수 있게 간단한 예를 들어보자
    • 실행 엔진이 핸들러에게 임시 테이블을 만들라고 요청
    • 다시 실행 엔진은 WHERE 절에 일치하는 레코드를 읽어오라고 핸들러에 전달
    • 읽어온 레코드들을 1번에서 준비한 임시 테이블로 저장하라고 다시 핸들러에게 요청
    • 데이터가 준비된 임시 테이블에서 필요한 방식으로 데이터를 읽어 오라고 핸들러에게 다시 요청
    • 최종적으로 실행 엔진은 결과를 사용자나 다른 모듈로 넘김
  4. 핸들러(스토리지 엔진) 핸들러는 가장 밑단에서 실행 엔진의 요청에 따라 데이터를 디스크로 저장하고 읽어 오는 역할을 담당한다. 핸들러는 결국 스토리지 엔진을 의미하며, MyISAM 테이블을 조작하는 경우에는 핸들러가 MyISAM 스토리지 엔진이 되고 InnoDB 테이블을 조작하는 경우 핸들러가 InnoDB 스토리지 엔진이 된다.

 

 

쿼리 캐시

MySQL 서버에서 쿼리 캐시 (Query Cache)는 SQL의 실행 결과를 메모리에 캐시하고, 동일 SQL 쿼리가 실행되면 테이블을 읽지 않고 즉시 결과를 반환하기 때문에 매우 빠른 성능을 보였다. 하지만 쿼리 캐시는 테이블의 데이터가 변경되면 캐시에 저장된 결과 중에서 변경된 테이블과 관련된 것들은 모두 삭제(Invalidate) 해야 했다. 이는 심각한 동시 처리 성능 저하를 유발한다.  결국 MySQL 8버전에서 쿼리 캐시는 제거되었고, 관련 시스템 변수도 모두 제거됐다.

 

 

스레드 풀 (Thread Pool)

MySQL 서버에서 스레드 풀은 내부적으로 사용자의 요청을 처리하는 스레드 개수를 줄여서 동시 처리되는 요청이 많다 하더라도 MySQL 서버의 CPU가 제한된 개수의 스레드 처리에만 집중할 수 있게 해서 서버의 자원 소모를 줄이는 것이 목적이다. 제한된 수의 스레드만으로 CPU가 잘 처리하도록 유도한다면 CPU의 프로세스 친화도(Processor affinity)도 높이고 운영체제 입장에서는 불필요한 컨텍스트 스위치를 줄여 오버헤드를 낮출 수 있다.

Percona Server의 스레드 풀은 기본적으로 CPU 코어의 개수만큼 스레드 그룹을 생성하는데, 스레드 그룹의 개수는 시스템 변수를 변경해서 조정할 수 있다. Percona Server 스레드 풀 플러그인은 선순위 큐와 후순위 큐를 이용해 특정 트랜잭션이나 쿼리를 우선적으로 처리할 수 있는 기능도 제공한다. 이렇게 먼저 시작된 트랜잭션 내 속한 SQL을 빨리 처리해주면 해당 트랜잭션이 가지고 있던 잠금이 빨리 해제되고 잠금 경합을 낮춰서 전체적인 처리 성능을 향상시킬 수 있다.

 

 

트랜잭션 지원 메타데이터

메타데이터란 테이블 구조 정보와 스토어드 프로그램등 정보를 데이터 딕셔너리 또는 메타데이터라고 한다. 8버전 이후 부터는 메타데이터를 InnoDB의 테이블에 저장하도록 개선됐으며, 트랜잭션 기반의 InnoDB 스토리지 엔진에 저장되도록 개선되면서 이제 스키마 변경 작업 중 비정상적으로 종료되어도 완전한 성공이나 실패로 정리된다. (트랜잭션처리)

 

'Programming > Database' 카테고리의 다른 글

Real MySQL - 엔진 1  (0) 2023.07.18