MySQL 이름의 유래
MariaDB, 아들 맥스의 이름을 딴 MaxDB 등이 그러하다.서버 계층(Server Layer)의 캐시 관리
Query Cache (Deprecated)
Table Open Cache & Definition Cache
오픈된 테이블의 핸들러 정보와 테이블 구조(Metadata)를 메모리에 보관한다. 이를 통해 매번 디스크에서 테이블 정의 파일을 읽어오는 비용을 절감한다.
쉽게 요약하자면, 리소스 효율성으로 맞춰진 캐시들이다.
Table Open Cache
Table Definition Cache
InnoDB 엔진의 핵심, Buffer Pool
Data Page Caching
LRU (Least Recently Used) List
한정된 메모리 자원을 관리하기 위해 최근에 가장 사용되지 않은 데이터를 방출하는 알고리즘이다. MySQL은 대량 스캔 작업이 버퍼 풀을 오염시키는 것을 방지하기 위해 리스트를 Old와 New 영역으로 나누어 관리하는 변형 LRU를 사용한다.
MySQL의 LRU List 기법은 일반적인 LRU 원리에서 Midpoint Insertion Strategy라는 영리한 기법을 더한 방식이다.
기존 LUR 기법을 사용하면 발생할 수 있는 문제
LRU List의 방식
Change Buffer
성능 가속을 위한 인덱스 및 로그 버퍼
운영체제 및 하드웨어와의 상호작용
MySQL이 데이터를 처리하는 과정은 크게 다음과 같은 흐름을 따른다.
동작 원리
사용자 요청 -> 쿼리 파싱 및 최적화 -> Buffer Pool 탐색 (Memory) -> 데이터 페이지 존재 여부 확인 -> (없을 시) Disk I/O 호출 -> Buffer Pool 적재 -> 결과 반환MySQL 엔진
정의
두뇌 역할을 하는 서버 계층을 의미한다.핵심 역할
구분
커넥션 핸들러
교통 정리 역할도 수행한다.SQL 파서(SQL Parser)
Parse Tree라는 구조로 만든다.SELECT, *, FROM, User 등 키워드 단위로 문장을 분리한다.전처리기(Preprocessor)
옵티마이저
옵티마이저는 쿼리를 실행하는 수만 가지 방법 중 가장 비용(시간/자원)이 적게 드는 방법을 찾는 역할을 한다.
옵티마이저는 단순히 오타를 고치거나 공백을 없애는 사소한 수준을 넘어, 결과값만 같다면 과정은 완전히 뜯어고쳐도 된다는 원칙 아래 움직인다.
동작 원리
A 인덱스를 쓰는게 빠즐지 B 인덱스를 쓰는 게 빠를지 결정한다.SQL문은 개발자가 짜는 것일텐데 어떻게 최적화한 다는 말일까?
무엇을(What)가져올지만 말하는 선언적 언어이다.서울역에서 강남역까지 가고싶다.고 작성하면 옵티마이저는 지금은 퇴근 시간이니까 지하철 2호선이 가장 빠를 것이다. 교통체증이 심해서 도로는 막을 것이다. 비용을 계산해봐야겠다.는 어떻게(How)의 역할을 한다.논리적 최적화 (Query Transformation)
물리적 최적화 (Cost-based Optimization, CBO)
캐시 및 버퍼가 위치하는 계층
InnoDB Buffer Pool(데이터 페이지 캐시)와 Change Buffer가 위치한다.스토리지 엔진 계층
정의
핵심 역할
물리적인 데이터 읽기/쓰기 (I/O 관리)
이름이 김철수인 사람을 찾아줘라는 요청을 하면 실무자 역할을 하는 스토리지 엔진이 하드디스크나 메모리에서 해당 데이터가 담긴 페이지를 찾아낸다.Index 관리
트랜잭션 관리(ACID 준수)
잠금(Locking)과 동시성 제어
엔진의 종류 및 선택
데이터 핸들링
핸들러 API
데이터를 한줄 읽어라는 명령을 한다.Handler API를 통해 명령을 전달한다.(ha_index_read, ha_write_row)A라는 테이블에서 데이터를 가져와라는 명령을 내릴 때, 직접 하드디스크를 뒤지는 대신, A 테이블 전용 핸들러를 호출한다. 전용은 단순히A 테이블에는 A 핸들러만 있다.는 뜻을 넘어 A 테이블을 작업하는 1번 작업자에게는 1번 전용 핸들러를 준다.는 의미에 가깝다.현재 내가 어디까지 읽었는지(Corsor), 어떤 데이터를 잠그고 있는지(Locking) 같은 아주 사적인 정보들이 담겨져 있다.전용 해들러 객체를 가지는 것이다.원리
캐시로서의 역할
버퍼로서의 역할
캐시전략
버퍼 풀의 데이터 적재 프로세스
버퍼 풀은 전체 리스트를 `New Sublist(자주 쓰는 데이터)와 Old Sublist(갓 들어온 데이터)로 나눈다.
이러한 구조를 사용하는 이유는 버퍼 풀 오염(Buffer Pool Pollution)을 방지하기 위해서이다.
동작 원리
정의
원친적인 방법
체인지 버퍼 방법
나중에 이 페이지가 오면 이 페이지를 수정하라는 메모만 남겨두는 방식이다.왜 보조 인덱스에만 사용하는가?
중복이 허용되는 인덱스에만 작동한다.왜 PK는 안되는가?
**미뤄둔 작업은 언제 동작하는가?(Merge 과정)
배경
B+Tree 구조이다. 아무리 빨라도 루트 노드에서 리프 노드까지 여러 단계를 거쳐 내려가야 한다.O(log n)의 시간이 걸린다.Hash 인덱스이다.O(1) 속도를 자랑한다.핵심 원리
어댑티브(Adaptive, 적응형)하게 작동한다.해시 테이블(Hash Table)에 기록.메모리상의 데이터 위치로 바로 이동한다.WHERE id = 100처럼 딱 하나의 값을 찾는 동등 비교(Point Lookup)가 압도적으로 많을 때.사용자가 데이터를 수정하면 MySQL(InnoDB)는 두 가지 동작을 한다.
이때, 매번 수천 명의 사용자가 데이터를 바꿀 때마다 하드디스크에 있는 리두 로그 파일을 직접 열어서 적으려면 서버는 큰 부담을 가질 것이다.
그래서 메모리의 아주 작은 공간에 먼저 기록해 두는데, 이 공간이 바로 로그 버퍼이다.
사용하는 이유
동작 원리(WAL, Write-Ahead Logging)
로그 버퍼라는 메모리 공간에 아주 작게 기록한다.여담
금융 서비스나 이커머스에서 가장 중요한 것은 내 돈이 정확히 전달되었는가이다.
InnoDB는 ACID(원자성, 일관성, 격리성, 지속성) 원칙을 철저히 따른다.
Undo Log
Rado Log
READ COMMITTED 수준에서 발생할 수 있는 현상으로, 한 트랜잭션 내에서 똑같은 SELECT 쿼리를 두 번 날렸는데 그 사이에 다른 트랜잭션이 데이터를 수정/커밋하여 결과값이 다르게 나타나는 현상을 의미한다.배경
정전이되거나 천재지변이 일어나면 어떻게 될 것인가? 해당 페이지는 앞부분은 새 데이터고 뒷부분은 옛날 데이터인 깨진 데이터(Torn Page)가 되어버린다.해결책 : Doublewrite Buffer
복구 과정
참고
.frm이라는 파일에 저장해서 매번 읽어왔다. 하지만 MySQL 8.0부터는 이를 DB 내부의 시스템 테이블에 저장하고, 자주 쓰는 정보는 Dictionary Cache에 올려둔다.정의
역할
참고
대형 서비스에서는 수만 개의 테이블이 존재할 수 있다.
속도
동시성
table_open_cache는 앞서 언급한 대로 스레드별로 핸들러를 가질 수 있게 넉넉해야 한다. 접속자가 폭주하는데 이 캐시가 작으면, 핸들러를 새로 만드느라 CPU 점유율이 치솟을 수 있다.시스템 모니터링 대시보드를 볼 때 Opened_tables라는 지표를 확인해보자. 이 숫자가 실시간으로 계속 빠르게 올라가고 있다면, 현재 Table Cache 크기가 너무 작아서 DB가 계속 테이블을 새로 열고 닫느라 부하가 쌓여 병목이 발생하는 증거이다.
이때 캐시 히트율이 낮아보이는데, table_open_cache 설정을 검토해 보는게 어떤가 생각을 해보자.
정의
동작 원리
SELECT * FROM users WHERE id=1이라는 쿼리를 날리면, DB는 이 문자을 키(Key)로, 결과 데이터를 값(Value)으로 메모리에 저장한다.재요청 시
현재 사용하지 않는 이유
쿼리 캐시 VS 버퍼 풀
쿼리 캐시와 InnoDB 버퍼 풀을 햇갈려햔다고 종종 이야기가 들리곤 했다.
하지만 둘은 완전히 다른 계층이다.
쿼리 캐시
버퍼 풀
참고
핸들러 객체
데이터 페이지에 5번행을 읽어와라고 명령하면, 핸들러가 실제 스토리지 엔진(InnoDB 등)에 접근해 데이터를 가져온다.File Descriptor(FD)
Too many open files라는 유명한 에러를 마주하게 된다.Data Page
보조 인덱스(Secondary Index)
CREATE INDEX로 추가하는 일반 인덱스들을 의미한다.클러스터링 인덱스
찾아보기라면, 클러스터링 인덱스는 책 내용 그 자체가 특정 순서로 정렬되어 있는 것과 같다.페이지 분할현상이 발생해 수정 작업이 무거워질 수 있다.Undo Log
데이터를 변경했을 때 변경하기 전의 이전 값을 저장해두는 공간이다.
주요 목적
Redo Log
디스크에 안전하게 기록하기 위한로그이다.레코드 수준 잠금(Record-level Lock)
레코드(행, Row) 하나하나에 각각 락을 거는 방식이다.Global Lock