개요
InnoDB 버퍼 풀은 데이터와 인덱스 페이지를 메모리에 캐싱하는 영역임 디스크 I/O를 획기적으로 줄여 지연 시간을 낮추는 게 목적임 InnoDB 스토리지 엔진(트랜잭션, MVCC, 행 단위 락 지원) 성능의 심장부라 할 수 있음
쉽게 말해, 자주 쓰는 데이터와 인덱스를 디스크 대신 메모리에 올려두고 처리하는 구조임
버퍼 풀 구성 요소
버퍼 풀에는 주로 이런 페이지(기본 16KB)가 올라옴
- 데이터 페이지: 실제 테이블 로우(Row)가 저장된 페이지
- 인덱스 페이지: B-Tree 인덱스 노드 페이지 (PK 및 세컨더리 인덱스 포함)
- 기타 관리 페이지: UNDO 페이지, 트랜잭션/MVCC 관리에 필요한 메타데이터 등
핵심 개념
페이지 캐싱
InnoDB는 디스크 데이터를 페이지 단위로 다룸 클라이언트가 특정 로우를 읽고 싶어 하면, 그 로우가 속한 페이지 전체를 버퍼 풀로 가져옴 이후 같은 페이지에 있는 다른 로우를 읽을 때는 디스크를 다시 보지 않고 버퍼 풀(메모리)에서 바로 조회함
더티 페이지와 쓰기 지연
애플리케이션이 데이터를 변경(INSERT, UPDATE)하면,
- 버퍼 풀에 적재된 페이지가 메모리상에서 먼저 수정됨
- 이 페이지는 ‘더티 페이지(Dirty Page)’(디스크와 내용이 다른 상태)로 표시됨
- 변경 내용은 즉시 디스크 데이터 파일에 쓰지 않고, 백그라운드 스레드가 모아서(Batch) 디스크에 반영(Flush)함
이렇게 모아서 쓰면 랜덤 I/O를 줄이고, 디스크 쓰기 효율을 올릴 수 있음
리두 로그 (Redo Log)
InnoDB는 WAL(Write-Ahead Logging) 방식을 사용함 데이터 페이지를 디스크에 쓰기 전에, 먼저 리두 로그에 변경 내용을 기록함
트랜잭션 커밋 흐름 요약
- 버퍼 풀의 페이지 수정 (→ 더티 페이지)
- 리두 로그 버퍼에 변경 내역 기록
- 커밋 시점: 리두 로그를 디스크로 동기화 (fsync)
- 애플리케이션에 커밋 성공 응답
- (이후) 더티 페이지는 백그라운드에서 천천히 디스크에 플러시
서버가 크래시 나도, 디스크에 반영 안 된 더티 페이지 내용은 리두 로그를 적용해 복구할 수 있음 (일관성 보장)
LRU 기반 페이지 교체
버퍼 풀 크기는 한정되어 있어, 새 페이지를 로드할 자리가 없으면 기존 페이지를 교체(Eviction)해야 함 InnoDB는 단순 LRU가 아닌, LRU 리스트를 “Young 영역"과 “Old 영역"으로 나누는 변형된 알고리즘을 사용함 (이는 Full Table Scan 같은 대용량 순차 스캔이 버퍼 풀의 ‘핫 데이터’를 밀어내는 상황을 방지하기 위함)
핵심은 “최근에 자주 쓰인 페이지는 오래 남기고, 오래 안 쓰인 페이지부터 내보낸다"는 것
읽기/쓰기 동작 흐름
읽기 경로
- 클라이언트가 특정 데이터 조회 요청
- InnoDB가 해당 페이지가 버퍼 풀에 있는지 확인
- 있으면 (Cache Hit): 메모리에서 즉시 반환 (매우 빠름)
- 없으면 (Cache Miss): 디스크에서 페이지를 읽어와 버퍼 풀에 적재 후 반환 (느림)
- → 버퍼 풀 히트율(Hit Rate)이 높을수록 디스크 I/O가 줄어 성능이 좋아짐
쓰기 경로
- 애플리케이션이 데이터를 변경하면 버퍼 풀의 페이지에 먼저 반영 (→ 더티 페이지가 됨)
- 변경 내용이 리두 로그에 기록됨
- 커밋 시점: 리두 로그가 우선 디스크에 안전하게 기록됨 (애플리케이션 응답 완료)
- 더티 페이지 자체는 백그라운드 스레드(Page Cleaner)가 디스크로 천천히 내려 보냄 (체크포인트 관리)
이 구조 덕분에 쓰기 트랜잭션이 많아도 애플리케이션은 비교적 빠르게 커밋 응답을 받을 수 있음
버퍼 풀 크기 설정
기본 원칙
innodb_buffer_pool_size 값은 전체 RAM, 워크로드 특성, 같은 서버에서 돌아가는 다른 프로세스를 모두 고려해서 잡아야 함
전형적인 전용 DB 서버 기준, 러프하게 전체 메모리의 50%~75% 정도를 할당함
스왑(Swap)은 절대 금물
버퍼 풀 크기를 욕심내서 크게 잡았다가 OS 스왑이 발생하면, 메모리가 디스크처럼 동작하게 되어 성능이 급격히 나빠짐 “버퍼 풀 히트율 조금 더 높이기"보다 “절대 스왑 안 나게 하기"를 우선하는 게 안전함
버퍼 풀 인스턴스
대용량 버퍼 풀(수십 GB 이상)일 경우, innodb_buffer_pool_instances를 조정하여 버퍼 풀을 여러 인스턴스로 나누면 락 경합을 줄여 동시성 향상에 도움이 될 수 있음
모니터링 지표와 튜닝
버퍼 풀 히트율
높은 히트율(예: 99% 이상)은 디스크 I/O가 적다는 뜻
SHOW ENGINE INNODB STATUS로 확인 가능함
워크로드 자체가 디스크를 많이 타는지, 읽기 패턴이 어떤지 같이 봐야 함
더티 페이지 비율
더티 페이지가 너무 많이 쌓이면(예: innodb_max_dirty_pages_pct), 플러시 작업이 몰려서 디스크가 갑자기 바빠지고 응답 지연이 발생할 수 있음
innodb_io_capacity 등을 조절해 더티 페이지가 적정 수준에서 꾸준히 플러시되도록 유도해야 함
정리
버퍼 풀은 읽기(캐싱)와 쓰기(지연/배치) 성능을 모두 책임지는 InnoDB의 핵심임 운영 시에는 스왑이 나지 않는 보수적인 크기에서 시작하고, 모니터링 지표(히트율, 더티 페이지, 플러시 지연)를 근거로 점진적으로 조정하는 접근이 안전함
MySQL 5.7, 8.0에서는 innodb_buffer_pool_size를 온라인(동적)으로 조정 가능함
서비스 중단 없이 부하 패턴 변화에 맞춰 버퍼 풀 크기를 늘리거나 줄일 수 있음