핵심 답변
MySQL은 디스크 I/O를 최소화하기 위해 InnoDB Buffer Pool에 데이터 페이지와 인덱스 페이지를 메모리에 캐싱하고, LRU 알고리즘으로 관리하며, 변경된 페이지(Dirty Page)를 백그라운드로 디스크에 기록합니다.

MySQL의 버퍼와 캐시는 크게 InnoDB Buffer Pool을 중심으로 동작하며, 다음과 같은 데이터를 메모리에 보관합니다:

활용 방식:

  1. 쿼리 실행 시 먼저 Buffer Pool에서 데이터 검색
  2. 없으면 디스크에서 읽어와 Buffer Pool에 캐싱 (페이지 단위)
  3. 수정된 데이터는 Dirty Page로 마킹하고 백그라운드 스레드가 디스크에 플러시
  4. 메모리가 부족하면 LRU(Least Recently Used) 알고리즘으로 오래된 페이지 제거
알아야 할 배경 개념

페이지 (Page)
InnoDB는 디스크와 메모리 간 데이터를 페이지라는 16KB 단위로 관리합니다. row 단위가 아닌 페이지 단위로 읽고 쓰는 이유는 디스크 I/O의 효율성 때문입니다.

LRU 알고리즘
Least Recently Used의 약자로, 가장 오래 사용되지 않은 데이터를 먼저 제거하는 캐시 교체 알고리즘입니다. InnoDB는 전통적인 LRU를 개선한 Midpoint Insertion Strategy를 사용합니다.

Dirty Page
메모리에서 수정되었지만 아직 디스크에 기록되지 않은 페이지를 말합니다. 체크포인트 시점이나 Buffer Pool 공간 부족 시 디스크로 플러시됩니다.

MVCC (Multi-Version Concurrency Control)
동시성 제어를 위해 데이터의 여러 버전을 유지하는 기법입니다. Undo 페이지가 이를 위해 사용됩니다.

더 깊이 파고들기

InnoDB Buffer Pool의 구조적 특징

InnoDB Buffer Pool은 단순한 LRU가 아니라 3가지 영역으로 나뉩니다:

새 페이지는 바로 LRU 리스트의 맨 앞이 아닌 Midpoint(Old 영역의 시작점)에 삽입됩니다. 이후 일정 시간 내에 다시 접근되면 Young 영역으로 승격됩니다. 이는 풀 테이블 스캔 같은 대량 읽기 작업이 Buffer Pool을 오염시키는 것을 방지합니다.

Change Buffer의 활용

세컨더리 인덱스 수정 시, 해당 인덱스 페이지가 Buffer Pool에 없다면 디스크에서 읽어와야 합니다. 이 때 Change Buffer가 변경사항을 임시 저장하고, 나중에 해당 페이지가 로드될 때 한꺼번에 병합(merge)합니다. 이는 랜덤 디스크 I/O를 대폭 줄여줍니다.

Adaptive Hash Index (AHI)

InnoDB는 자주 접근되는 인덱스 페이지에 대해 해시 인덱스를 자동 생성합니다. B-Tree 탐색은 O(log n)이지만, 해시 인덱스는 O(1)이므로 특정 패턴의 쿼리 성능이 크게 향상됩니다. 단, 모든 경우에 유리한 것은 아니며, 경합이 심한 환경에서는 비활성화하는 것이 나을 수 있습니다.

Flush 메커니즘

Dirty Page는 다음 상황에서 디스크로 기록됩니다:

MySQL 8.0의 변화

MySQL 8.0에서는 Query Cache가 완전히 제거되었습니다. Query Cache는 동일한 쿼리의 결과를 캐싱했지만, 테이블이 변경되면 관련 캐시를 모두 무효화해야 해서 오히려 성능 저하를 일으키는 경우가 많았습니다. 대신 Buffer Pool과 애플리케이션 레벨 캐싱(Redis 등)을 권장합니다.

시각화
InnoDB Buffer Pool 구조와 데이터 흐름 디스크 스토리지 데이터 파일 (.ibd) 인덱스 파일 (B-Tree) Redo Log (ib_logfile) Undo Log (MVCC용) InnoDB Buffer Pool (메모리) Young Sublist (약 63%) 자주 접근되는 Hot 페이지들 Data Page Index Page Dirty Page Midpoint Old Sublist (약 37%) 새로 읽힌 페이지가 처음 들어오는 곳 New Page New Page Change Buffer 세컨더리 인덱스 변경사항 임시 저장 Adaptive Hash 자주 접근하는 페이지 해시 인덱스 자동 생성 Read Flush (Dirty) 쿼리 실행 → Buffer Pool 먼저 검색 → 없으면 디스크 읽기

다이어그램 설명:

주요 버퍼/캐시 구성요소 비교
구성요소 저장 데이터 목적 특징
Buffer Pool 데이터/인덱스 페이지 디스크 I/O 최소화 LRU + Midpoint 전략, 가장 중요한 캐시
Change Buffer 세컨더리 인덱스 변경사항 랜덤 I/O 감소 나중에 페이지 로드 시 병합 (Merge)
Adaptive Hash Index 자주 접근하는 인덱스의 해시 검색 속도 향상 자동 생성/제거, O(1) 검색
Log Buffer Redo Log 엔트리 트랜잭션 내구성 주기적으로 디스크 Redo Log로 플러시
Query Cache 쿼리 결과 (제거됨) 동일 쿼리 재사용 MySQL 8.0에서 완전 제거
함께 알면 좋은 개념