MySQL 8.0부터는 InnoDB가 기본 스토리지 엔진으로 채택되었으며 트랜잭션, 외래 키, MVCC, 충돌 제어 같은 고급 기능을 지원하는 강력한 저장 엔진이다.
단순히 데이터를 디스크에 저장하는 데 그치지 않고 메모리 관리, 로그 처리, 쓰기 최적화까지 수행하는 복잡한 내부 구조를 갖고 있다.
🤔 원래 이런거 지원해야하는거 아니야???
그럼 InnoDB를 말고 다른 DB 스토리지 엔진에 대해서 알아보자.
MyISAM은 MySQL 5.1 이전 버전에서 기본(Default) 엔진이었다.
그 당시에는 트랜잭션이나 외래 키 같은 기능보다는 단순하고 빠른 읽기 성능이 중요했기 때문에 MyISAM이 많이 쓰였다.그래서 MyISAM은 트랜잭션, 외래 키(FK), 동시성 처리와 같은 기능은 없었다. 이를 개선한 것이 InnoDB 인데 처음엔 느리다는 이미지가 있었지만, 버전이 올라가면서 성능 최적화 + 기능성 + 안정성 모두 압도적이 되어서 MyISAM을 대체하게 되었다.
결론 : 실무에서는 지금 MyISAM을 사용하는 경우는 거의 없고 일부 특수 용도(정적 읽기 전용, 검색 인덱스 캐시 등) 외에는 InnoDB가 무조건 권장된다.
(MyISAM 에서도 정규화 (무결성 보장 X), 인덱스를 사용할 수는 있음)
구조는 크게 메모리 구조(In-Memory Structures)와 디스크 구조(On-Disk Structures)로 나뉘고 둘은 운영체제 캐시(=I/O 인터페이스)를 통해 상호작용한다.
버퍼 풀(Buffer Pool)은 InnoDB에서 테이블과 인덱스 데이터를 캐시하는 주 메모리 공간이다.
디스크 접근을 최소화하고, 자주 조회되는 데이터를 메모리에서 직접 처리할 수 있도록 하여 전체 성능을 크게 향상시킨다.
버퍼 풀은 변형된 LRU 알고리즘을 사용하여 페이지를 관리한다.
New Sublist
와 Old Sublist
하위 목록으로 나뉜다.Change Buffer는 InnoDB가 보조 인덱스(Secondary Index)에 대한 변경 작업 (INSERT, UPDATE, DELETE)을 수행할 때
해당 인덱스 페이지가 Buffer Pool(메모리)에 없다면 즉시 디스크를 읽지 않고 변경 내용을 임시 저장해두는 특수 캐시 구조다.
🤔 그럼 왜 굳이 메모리에 임시로 저장해둘까?
보조 인덱스는 정렬되지 않은 상태에서 삽입/삭제가 발생하고 이로 인해 디스크의 여러 위치를 랜덤하게 접근해야 한다.
하지만 디스크는 랜덤 I/O에 매우 취약하고 느리기 때문에 변경이 발생할 때마다 매번 디스크를 읽어오는 건 성능 낭비가 크다.그래서 InnoDB는 보조 인덱스 페이지가 메모리에 없을 경우 변경 내용을 바로 디스크에 적용하지 않고 Change Buffer에 임시로 기록해둔다.
→ 해당 Buffer Pool에 로드될 때 미뤄뒀던 변경 내용을 한꺼번에 병합하면서 불필요한 디스크 접근을 줄이고 전체 성능을 높이는 구조
보조 인덱스에 대한 변경 작업(INSERT, UPDATE, DELETE)이 발생했을 때 해당 인덱스 페이지가 버퍼 풀에 존재하지 않고
이후 해당 보조 인덱스 페이지가 다른 쿼리나 작업에 의해 버퍼 풀에 로딩되면 변경 버퍼의 내용이 해당 페이지에 병합(Merge) 되고
적응형 해시 인덱스(AHI)는 InnoDB가 자주 조회되는 B+Tree 인덱스 페이지의 검색 패턴을 감지하고 자동으로 해시 인덱스를 생성함으로써 인덱스 검색 속도를 비약적으로 향상시키는 기능이다.
적응형 해시 인덱스(AHI)가 왜 빠른가?
- 이미 찾은 주소를 해시 값으로 테이블로 저장해놓고 다음 요청에 이 테이블을 활용하는 것!
SELECT * FROM user WHERE email = 'jay@domain.com';
로그 버퍼(Log Buffer)는 InnoDB에서 트랜잭션 중 변경된 데이터를 디스크에 기록하기 전까지 임시 저장하는 메모리 공간이다.
이 공간에는 Redo Log에 기록될 내용이 담기며, 디스크에 기록되기 전까지는 로그 버퍼에 머문다.
🤔 아까 Change Buffer 랑 비슷한거 아니야?
- Log Buffer는 모든 변경 이력을 기록해 복구 가능하게 만드는 트랜잭션 로그 공간
- Change Buffer는 보조 인덱스 페이지가 없을 때 변경 내용을 임시 저장해 불필요한 디스크 읽기를 줄이는 캐시
⚠️ 주의 사항
Log Buffer는 임시 저장소일 뿐, 복구를 보장하지 않는다.
진짜 복구의 근거는 Redo Log 파일이기 때문에 커밋 시점에 Log Buffer → Redo Log로 얼마나 빨리 플러시하느냐가 핵심이다.
InnoDB는 데이터를 디스크에 저장할 때, 논리적 구조와 물리적 구조로 나누어 저장 구조를 설계한다.
논리적 구조: 데이터베이스 입장에서 보이는 구조 (테이블, 인덱스 등)
물리적 구조: 실제 디스크 파일과 저장 단위 (tablespace, 로그 등)
Table(테이블)은 데이터베이스에서 데이터를 행(Row)과 열(Column)로 저장하는 기본 단위이다.
하지만 InnoDB에서는 row가 단순히 저장되는 것이 아니라, 클러스터형 인덱스(Primary Key B+Tree)의 구조 안에 함께 저장된다.
기본 키로 조회하거나 범위 검색할 때 매우 빠름
인덱스는 데이터를 빠르게 찾기 위한 자료구조이며, InnoDB는 B+Tree 구조의 인덱스를 사용한다.
조회 성능 향상은 크지만, 보조 인덱스만으로는 row 전체를 알 수 없음
테이블과 인덱스 데이터를 실제로 디스크에 저장하는 물리적 공간
InnoDB는 데이터를 Tablespace
라는 단위로 파일에 저장함
대표적인 구조:
ibdata1
: 공유 테이블스페이스 (구버전).ibd
: 각 테이블별 독립 저장 파일 (파일-퍼-테이블 모드)데이터가 실제로 어느 파일에 저장되는지 이해하는 핵심
InnoDB는 디스크 쓰기 중 장애가 발생할 경우를 대비해
데이터를 먼저 임시 버퍼 영역에 두 번 기록하는 방식으로 디스크 손상을 방지한다.
안정성 보장을 위한 쓰기 보호 메커니즘
트랜잭션의 변경 이력(무엇을 변경했는지)을 기록하는 로그 파일
ib_logfile0
, 등) 에 기록됨WAL(Write-Ahead Logging)의 핵심 요소
데이터의 영속성과 복구 가능성 확보
트랜잭션의 이전 값을 저장하는 로그
→ 롤백, 그리고 MVCC(다중 버전 동시성 제어) 구현의 핵심
DELETE
나 UPDATE
전에 이전 값을 Undo Log에 저장트랜잭션의 정합성, MVCC의 기반이 되는 구조
지금까지 InnoDB가 데이터를 디스크에 저장할 때 사용하는 구조를 살펴봤다.
단순히 데이터를 저장하고 조회하는 것처럼 보이지만, 내부적으로는 정렬된 인덱스 구조, 로그 기록, 복구를 위한 이중 버퍼링 등 다양한 최적화와 안정성 장치가 작동하고 있는 것이다.
앞으로의 인덱스 튜닝, 트랜잭션 처리, 성능 최적화에서 이 구조들이 어떤 식으로 영향을 주는지 하나씩 연결해보자.