728x90
InnoDB 스토리지 엔진 아키텍처
InnoDB는 MySQL에서 사용할 수 있는 스토리지 엔진 중에서 거의 유일하게 레코드 기반의 Lock을 제공하고 있으며,
높은 동시성 처리가 가능하고 또한 한정적이며 성능이 뛰어납니다.

InnoDB 스토리지 엔진의 특성
- 프라이머리 키(PK)에 의한 클러스터링
- InnoDB의 모든 테이블은 기본적으로 PK를 기준으로 클러스터링 되어 저장됩니다.
- 즉, PK값 순서대로 디스크에 저장되고, 이로 인해 PK에 의한 레인지 스캔은 상당히 빨리 처리됩니다.
- 잠금이 필요 없는 일관된 읽기
- InnoDB 스토리지 엔진은 MVCC라는 기술을 이용해 락을 걸지 않고 읽기 작업을 수행합니다.
- 락을 걸지 않기 때문에 InnoDB에서 읽기 작업은 다른 트랜잭션이 가지고 있는 락을 기다리지도 않습니다.
- 외래키 지원
- InnoDB 스토리지 엔진 레벨에서 지원하는 기능으로 MyISAM이나 MEMORY 테이블에서는 사용할 수 없습니다.
- 외래키는 부모 테이블과 자식 테이블 모두 해당 컬럼에 인덱스 생성이 필요하고,
변경 시에는 반드시 부모 테이블과 자식 테이블에 데이터가 있는지 체크하는 작업이 필요합니다. - 이때, 잠금이 여러 테이블로 전파되고,그로 인해 데드락이 발생할 수 있습니다.
- foreign_key_checks 시스템 변수를 OFF로 설정하면 외래 키 관계에 대한 체크 작업을 일시적으로 멈출 수 있습니다.
- 이때, 부모와 자식 테이블 간의 관계가 깨진 상태로 그대로 유지해도 된다는 것을 의미하지는 않습니다.
반드시 일관성을 맞춰준 후 다시 외래 키 기능을 활성화해야 합니다.
- 자동 데드락 감지
- 데드락 감지 스레드가 주기적으로 잠금 대기 그래프를 검사해 교착 상태에 빠진 트랜잭션들을 찾아서 그 중 하나를 강제 종료합니다.
- 어떤 트랜잭션을 먼저 강제 종료할 것인지를 판단하는 기준은 트랜잭션의 언두 로그 양이며, 언두 로그 레코드를 더 적게 가진 트랜잭션이 롤백의 대상이 됩니다.
- 자동화된 장애 복구
- 오라클의 아키텍처 사용

InnoDB 버퍼 풀(Buffer Pool)
- 디스크의 데이터 파일이나 인덱스 정보를 메모리에 캐시해 두는 공간입니다.
- 쓰기 작업을 지연시켜 일괄 작업으로 처리할 수 있게 해주는 버퍼 역할도 같이 수행합니다.
(버퍼 풀이 변경된 데이터를 모아서 처리하게 되면 랜덤한 디스크 작업의 횟수를 줄일 수 있습니다) - 버퍼 풀의 크기는 innodb_buffer_pool_size로 설정하는데,
일반적으로 전체 장착된 물리 메모리의 50 ~ 80% 수준에서 버퍼 풀의 메모리를 결정합니다.
(운영체제와 각 클라이언트 스레드가 사용할 메모리도 충분히 고려해서 결정해야 합니다) - InnoDB 버퍼 풀은 아직 디스크에 기록되지 않은 변경된 데이터를 가지고 있습니다.
(이러한 데이터를 가지고 있는 페이지를 더티 페이지(Dirty page)라고 합니다) - 이러한 더티 페이지는 InnoDB에서 주기적으로 또는 어떤 조건이 되면 체크포인트 이벤트가 발생하는데,
이때 쓰기 스레드가 필요한 만큼의 더티 페이지만 디스크로 기록합니다.
리두(Redo) 로그 및 로그 버퍼
- 데이터를 버퍼링해 두기 위해 존재하는 InnoDB 버퍼 풀로만은 ACID를 보장할 수 없는데, 이를 위해 변경된 내용을
순차적으로 디스크에 기록하는 로그 파일을 가지고 있습니다. 이것을 리두 로그라고 합니다. - 리두 로그 덕분에 DBMS 데이터는 버퍼링을 통해 한꺼번에 디스크에 변경된 내용을 처리할 수 있습니다.
- 하지만 사용량(특히 변경 작업)이 매우 많은 DBMS 서버의 경우에는 이 리두 로그의 기록 작업이 큰 문제가 되는데, 이러한 부분을 보완하기 위해 ACID 속성을 보장하는 수준에서 버퍼링하게 된다. 이러한 리두 로그 버퍼링에 사용되는 공간이 로그 버퍼입니다.
참고.
ACID는 데이터베이스에서 트랜잭션의 무결성을 보장하기 위해 반드시 필요한 4가지 요소(기능)를 의미합니다.
"A"는 Atomic의 첫 글자로, 트랜잭션은 원자성 작업이어야 함을 의미한다.
"C"는 Consistent의 첫 글자로, 일관성을 의미한다.
"I"는 Isolated의 첫 글자로, 격리성을 의미한다.
"D"는 Durable의 첫 글자이며, 한번 저장된 데이터는 지속적으로 유지돼야 함을 의미한다.
바이너리 로그 및 릴레이 로그
- 바이너리 로그(Binary Log)
- 마스터 서버에서 실행되는 DML과 DDL 가운데 데이터의 구조나 내용을 변경하는 모든 "쿼리 문장" 또는 "변경된 레코드 값"은 바이너리 로그에 기록됩니다.
- Statement 포맷 방식 : 쿼리 문장 기록
- Row 포맷 방식 : 변경된 레코드 값 기록
- 슬레이브 서버에서 변경 내역을 요청하면 마스터 장비의 프로세스 가운데 Binlog dump 스레드가 그 바이너리 로그를 읽어 슬레이브로 넘깁니다.
- 만약 하나의 마스터 서버에 10개의 슬레이브가 연결돼 있다면 Binlog dump 스레드는 10개가 표시될 것입니다.
- 기술적으로 바이너리 로그가 활성화되면 어떤 MySQL 서버든 마스터가 될 수 있습니다.
- 마스터 서버에서 실행되는 DML과 DDL 가운데 데이터의 구조나 내용을 변경하는 모든 "쿼리 문장" 또는 "변경된 레코드 값"은 바이너리 로그에 기록됩니다.
- 릴레이 로그(Relay Log)
- 마스터 서버가 바이너리 로그를 가지고 있다면 슬레이브 서버는 릴레이 로그를 가지고 있습니다.
- 슬레이브 서버의 I/O 스레드는 마스터 서버에 접속해 변경 내역을 요청하고, 받아온 변경 내역을 릴레이 로그에 기록합니다.
- 그리고 슬레이브 서버의 SQL 스레드가 릴레이 로그에 기록된 변경 내역을 재실행함으로써 슬레이브의 데이터를 마스터와 동일한 상태로 유지합니다.
- I/O 스레드와 SQL 스레드는 마스터 서버에서는 기동되지 않습니다.
인서트 버퍼(=체인지 버퍼)

- RDBMS에서 레코드가 INSERT되거나 UPDATE 될 때, 데이터 파일을 변경하는 작업 뿐 아니라 해당 테이블에 포함된 인덱스를 업데이트하는 작업도 필요합니다.
- 그런데 클러스터형 인덱스의 경우 정렬된 순서로 삽입되는 반면, 보조 인덱스의 경우 일반적으로 유니크하지 않고 정렬되지 않은 채 처리가 되기 때문에 최신 상태로 유지하기 위해서는 상당한 I/O가 발생하게 됩니다.
- 그래서 InnoDB는 변경해야 할 인덱스 페이지가 버퍼 풀에 있으면 업데이트를 수행하지만, 그렇지 않고 디스크로부터 읽어와서 업데이트해야 한다면 이를 즉시 실행하지 않고 인서트 버퍼(Insert Buffer)라는 임시 공간에 저장해 두고 바로 사용자에게 결과를 반환하는 형태로 성능을 향상 시키게 됩니다.
- 사용자에게 결과를 전달하기 전에 반드시 중복 여부를 체크해야 하는 유니크 인덱스는 인서트 버퍼를 사용할 수 없습니다.
- 인서트 버퍼에 임시로 저장돼 있는 인덱스 레코드 조각은 이후 백그라운드 스레드에 의해 병합되는데, 이 스레드를 인서트 버퍼 머지 스레드(Merge thread)라고 합니다.
- MySQL 5.5 버전부터는 innodb_change_buffering이라는 설정 파라미터가 새로 도입되어 작업의 종류별로 인서트 버퍼를 활성화할 수 있으며, 인서트 버퍼가 비효율적일 때는 인서트 버퍼를 사용하지 않게 설정할 수 있도록 개선되었습니다.
언두(Undo)로그
- 언두 영역은 UPDATE나 DELETE로 데이터를 변경했을 때 변경되기 전의 데이터(이전 데이터)를 보관하는 곳입니다.
- 언두의 데이터는 크게 두 가지 용도로 사용되는데,
- 첫 번째 용도가 바로 위에서 언급한 트랜잭션의 롤백 대비용이다.
- 두 번째 용도는 트랜잭션의 격리 수준을 유지하면서 높은 동시성을 제공하는 데 사용한다.
참고 도서 및 사이트
- 도서 : Real MySQL 8.0
728x90
'📁 Database > MySQL & MariaDB' 카테고리의 다른 글
| [MariaDB] MHA 구성(Part 1. MariaDB 10.11.8 설치) (0) | 2024.07.26 |
|---|---|
| [MySQL] LRU 리스트, Flush 리스트, Free 리스트 (0) | 2024.07.22 |
| [MySQL] MySQL 아키텍처 : Replication(복제) (0) | 2024.07.10 |
| [MySQL] [MY-011825] [InnoDB] Cannot add field ... which is greater than maximum allowed size (8126) 해결법 (0) | 2024.05.31 |
| [MySQL] 현재 사용자, 데이터베이스 확인 (0) | 2024.05.31 |