[Real MySQL] InnoDB 스토리지 엔진 아키텍처 요약

sa46lll·2023년 11월 29일
0

Real-MySQL

목록 보기
6/9

해당 글은 백은빈, 이성욱 님의 'Real MySQL 8.0 (1권)'을 학습하며 정리한 글입니다.

MySQL 스토리지 엔진 중 가장 많이 사용되는 InnoDB 스토리지 엔진을 알아보자.
주요 특징들 기준으로 보자!

1. 프라이어머리 키에 의한 클러스터링

InnoDB의 모든 테이블은 기본적으로 PK를 기준으로 클러스터링되어 저장된다. PK가 클러스터링 인덱스이기 때문에 범위 스캔이 상당히 빠르다.
다른 보조 인덱스(세컨더리 인덱스 혹은 넌클러스터링 인덱스)에 비해 비중이 높게 설정된다.

이와 달리, MyISAM 스토리지 엔진에서는 클러스터링 인덱스를 지원하지 않는다. 프라이머리 키는 단지 unique 제약을 가진 세컨더리 인덱스일 뿐이다.
추후 MyISAM 스토리지 엔진에 대해서도 정리하겠다.

2. 외래 키 지원

InnoDB 스토리지 엔진 레벨에서 지원하는 기능이다. 외래 키는 개발 환경의 DB에서 좋은 가이드 역할을 제시할 수 있다.
다만, 변경 시에 부모/자식 테이블의 데이터를 체크하는 과정에서 잠금이 여러 테이블로 전파되고, 데드락 발생 가능성이 있으므로 주의하자.
(실무에서는 데이터베이스 서버 운영의 불편함 때문에 생성하지 않는 경우도 있다.)

3. MVCC (Multi Version Concurrency Control)

멀티 버전 즉, 하나의 레코드에 대해 여러 개의 버전이 동시에 관리되는 기능이다. 잠금 없이 일관된 읽기를 제공하는 데 목적을 둔다.
InnoDB는 언두 로그(undo log)를 통해 MVCC를 구현한다.

MySQL은 READ_COMMITED가 기본 고립 수준이기 때문에, 아직 커밋되지 않은 데이터가 아닌, 변경 이전의 내용을 보관하고 있는 Undo 영역의 데이터를 반환한다.
이 과정을 MVCC라고 표현한다. 이 Undo 영역의 데이터는 필요로 하는 트랜잭션이 없을 때 비로소 삭제된다.

4. 잠금 없는 일관된 읽기 (Non-Locking Consistent Read)

InnoDB 스토리지 엔진은 MVCC를 이용해 잠금을 걸지 않고 읽기 작업을 수행한다. 잠금을 걸지 않기 때문에 다른 트랜잭션의 잠금을 기다리지 않고, 읽기 작업이 가능하다.
사용자가 레코드를 변경하고 커밋을 수행하지 않았더라도, 이 변경 트랜잭션이 사른 사용자의 select 작업을 방해하지 않는다. InnoDB는 변경되기 전의 데이터를 읽기 위해 언두 로그를 사용한다.

5. 자동 데드락 감지

InnoDB 스토리지 엔진은 내부적으로 잠금이 교착상태에 빠지지 않았는지 체크한다. 주기적으로 검사하고, 데드락이 발생했다면 해당 트랜잭션 중 하나를 강제 종료한다.
종료할 트랜잭션은 Undo 로그의 양으로 결정하며, 더 적게 가진 트랜잭션이 롤백의 기준이 된다. 언두 레코드를 적게 가졌다는 것은, 롤백을 해도 언두 처리를 해야할 내용이 적다는 것을 의미하고, 강제 롤백으로 인한 MySQL 부하도
덜 유발하기 때문이다.

6. 자동화된 장애 복구

InnoDB 스토리지 엔진은 매우 견고해서 데이터 파일이 손상되거나 MySQL 서버가 시작하지 못하는 경우는 거의 없다.
하지만, MySQL 서버와 무관하게 디스크나 서버 하드웨어 이슈로 자동으로 복구를 못하는 경우도 발생할 수 있다. 이 경우 InnoDB 데이터 파일은 기본적으로 MySQL 서버가 싲가할 때 항상 자동 복구를 수행한다.
만약 복구 불가한 손상이 있다면 MySQL 서버는 종료된다.

7. InnoDB 버퍼 풀

버퍼 풀은 디스크의 데이터 파일이나 인덱스 정보를 메모리에 캐시해두는 공간이다. 변경된 데이터를 모아서 처리하기 때문에 랜덤한 디스크 작업의 횟수를 줄일 수 있다.

버퍼 풀은 MySQL 5.7부터 동적으로 조절할 수 있도록 개선됐다. 가능하면 적절히 작은 값으로 설정해서 상황에 따라 메모리를 증가시키는 방법이 최적이다.
만약 이미 회사에서 MySQL 서버를 사용하고 있다면 해당 서버의 메모리 설정을 기준으로 버퍼 풀의 크기를 조정하자.

구체적으로는 다음과 같다.

운영체제의 전체 메모리 공간이 8GB 미만이라면, 50%를 버퍼 풀로 설정하자. 나머지 공간은 MySQL 서버와 OS, 다른 프로그램이 사용할 수 있는 공간으로 확보하는 것이다.
8GB 이상이라면, 50%부터 시작해서 조금씩 올려가자. 50GB 이상이라면 15GB ~ 30GB 정도를 운영체제와 다른 응용 프로그램을 위해 남겨두고 나머지를 버퍼 풀로 할당하자.

8. Double Write Buffer

InnoDB 스토리지 엔진은 데이터 파일에 변경된 내용을 기록하기 전에, 먼저 버퍼에 기록한다. 이를 Double Write Buffer라고 한다.
만약 MySQL 서버가 비정상 종료되었다면, 데이터 파일의 내용이 일관성이 없을 수 있을 수 있는데 이를 방지하기 위함이다.

데이터의 안정성을 위해 자주 사용되며, 한번 순차 디스크 쓰기를 하기 때문에 별로 부담되지 않는다. 특히, 데이터의 무결성이 매우 중요한 서비스에서는 활성화하는 것이 좋다.

9. Undo Log

InnoDB 스토리지 엔진은 트랜잭션과 격리 수준을 보장하기 위해 Undo Log를 통해 별도로 백업한다.

Undo Log는 크게 두 가지 용도로 사용된다.

  • 트랜잭션의 롤백 대비용
  • 트랜잭션의 격리 수준을 유지하면서 높은 동시성 제공

하지만, 트랜잭션이 장시간 유지되는 것은 Undo 로그를 계속 유지해야 하기 때문에 MySQL 서버에 오버헤드가 생길 수 있다.
따라서 트랜잭션은 가능한 빨리 롤백이나 커밋을 하는 것이 좋다.

10. 체인지 버퍼

레코드가 삽입, 업데이트될 때 데이터 파일을 변경하는 작업뿐 아니라 인덱스를 업데이트하는 작업도 필요하다. 이 때 즉시 실행하지 않고 임시 공간에 저장해 두고 바로 사용자에게 결과를 반환하는 형태로 성능을 향상시킨다.
이 임시 메모리 공간을 체인지 버퍼라고 한다. 체인지 버퍼가 차지하는 버퍼 풀 공간은 innodb_change_buffer_max_size로 설정할 수 있다.

11. Redo Log

Redo Log는 MySQL 서버가 비정상적으로 종료됐을 때 데이터 파일에 기록되지 못한 데이터를 잃지 않게 해주는 안전장치이다. 이것은 트랜잭션의 4가지 요소인 Durable과 관련된다.

12. 어댑티브 해시 인덱스

어댑티브 해시 인덱스는 InnoDB 스토리지 엔진이 자동으로 생성하는 인덱스이다. 사용자가 자주 요청하는 데이터에 대해 자동으로 생성하는 인덱스이며, 시스템 변수를 통해 활성화 여부를 설정할 수 있따.
B-Tree 인덱스의 탐색 시간은 보통 빠르지만, 많은 작업을 동시에 실행하면 CPU는 엄청난 프로세스 스케줄링을 하게 되고, 쿼리의 성능은 떨어지게 된다.

어댑시브 해시 인덱스는 이러한 B-Tree 검색 시간을 줄여주기 위해 도입된 기능이다. 자주 읽히는 데이터 페이지의 키 값으로 해시 인덱스를 만들고, 필요하면 즉시 찾아갈 수 있다.
B-Tree의 루트 노드부터 리프 노드까지 찾아가는 비용이 없어지고, CPU의 프로세스 스케줄링 비용도 줄어드는 것이다.

profile
비열한 커비

0개의 댓글