☁️ InnoDB 스토리지 엔진 아키텍처
스토리지 엔진은 MySQL 엔진에서 핸들러에 의해 전달된 명령을 수행하는 엔진이다. 데이터를 메모리에 쓰고 읽는 작업을 수행한다. 이 중 MySQL에서 가장 많이 사용되는 엔진은 InnoDB
스토리지 엔진이다.
InnoDB 스토리지 엔진은 내부적으로 Buffer pool
을 가지고 있어 데이터 캐싱을 지원한다. 또한 쓰기 작업에 대해 지연된 쓰기를 지원하고, 백그라운드 스레드가 주기적으로 더티 페이지를 확인하여 디스크에 데이터를 적재하고 동기화하는 작업을 수행한다.
InnoDB 스토리지 엔진은 레코드(튜플) 기반 잠금을 제공한다. 튜플 기반 잠금은 테이블 기반 잠금보다 좁은 범위 락을 사용하고, 각 트랜잭션이 튜플을 기준으로 동작할 수 있기에 높은 동시성 처리가 가능하다. 또한 데드락이 발생할 가능성이 적기에 안정적이며 성능이 뛰어나다.
이제 InnoDB가 지원하는 여러 기능 중 버퍼 풀에 대해 알아보자.
☁️ InnoDB 버퍼 풀
innoDB의 가장 핵심적인 부분이다. 버퍼 풀은 디스크의 데이터나 인덱스 정보를 메모리에 캐시해 두는 공간이다.
버퍼 풀은 전통적으로 버퍼 풀 전체를 세마포어를 사용하여 잠금을 관리하였는데, 이는 내부 잠금 경합을 많이 유발하여 버퍼 풀을 여러 개로 쪼개어 관리하는 방식으로 변경되었다. (기본적으로 버퍼 풀 인스턴스의 개수는 8개지만 전체 버퍼 풀을 위한 메모리 공간이 1GB 이하 수준이라면 버퍼 풀 인스턴스는 1개만 생성됨)
버퍼 풀의 내부 공간은 작은 페이지 크기의 조각으로 나누어져 관리된다. 이러한 페이지들을 관리하기 위해 innoDB는 크게 3개의 자료 구조를 관리한다.
LRU 리스트
: 버퍼 풀에 저장된 데이터를 관리플러시 리스트
: 디스크로 동기화 되지 않은 데이터(더티 페이지)를 관리프리 리스트
: 사용되지 않고 비어있는 영역
버퍼 풀의 메모리 공간을 늘리면 쿼리의 성능이 빨라진다. 디스크의 데이터를 메모리 공간인 버퍼 풀에 저장해놓기에 이 공간이 늘어난다면 캐싱할수 있는 데이터도 많아진다. 이는 쿼리의 성능 향상으로 이어진다. 버퍼 풀은 데이터 캐시와 버퍼링이라는 용도가 있는데 단순히 버퍼 풀의 메모리 공간만 늘린다면 캐시의 기능만 향상되는 것이다. 버퍼링 기능을 향상시키기 위해서는 리두 로그파일 크기를 조정하거나 더티 페이지를 디스크로 플러시하는 빈도를 조정해야 한다.
리두 로그와 언두 로그
Redo Log
는 트랜잭션의 쓰기 작업이 버퍼 풀의 데이터에 적용된 후의 결과를 저장하는 역할을 한다.
반대로 Undo Log
는 트랜잭션의 쓰기 작업이 버퍼 풀에 적용되기 전의 결과를 저장하는 역할을 한다.
버퍼 풀은 메모리에 존재한다. 즉 MySQL 서버가 비정상적으로 종료된다면, 디스크와 동기화 되지 않은 버퍼 풀의 정보는 사라지게 되어 데이터의 ACID를 보장할 수 없게된다. 이럴 때, 버퍼 풀의 작업 내용을 복구하기 위해 리두 로그를 사용한다. 리두 로그
는 리두 로그 파일
에 이러한 작업 내용을 저장하여 비정상적인 종료에 의한 복구가 필요할 때 리두 로그 파일을 사용한다.
InnoDB 엔진은 주기적으로 체크포인트
이벤트를 발생시켜 리두 로그와 버퍼 풀의 더티 페이지를 디스크로 동기화하는 작업을 수행한다.
언두 로그는 트랜잭션의 롤백, 읽기 작업에서의 MVCC를 지원하기 위해 사용되는 공간이다. 언두 로그 사용에는 유의해야할 점이 있는데 트랜잭션의 활성화가 오래 유지되지 않게 해야 한다는 것이다. 트랜잭션의 활성화가 오래 유지된다면 그만큼 언두 로그로 유지되어야 한다. 다른 트랜잭션이 동일 레코드에 접근하여 데이터를 변경하는 작업을 수행하고 종료하더라도 이 트랜잭션의 수행결과가 저장된 언두 로그는 삭제되지 않는다. 아직 해당 레코드를 사용하는 트랜잭션이 활성화 되어있기 때문이다. 따라서 언두 로그는 자주 모니터링해주는 것이 좋다.
InnoDB 버퍼 풀에 더티 페이지가 많으면 많을수록 디스크 쓰기 폭발(Disk IO Burst)가 발생할 확률이 높아진다. 디스크에 더티 페이지를 동기화하고 삭제하는 양보다 버퍼 풀에 더티 페이지가 쌓이는 양이 많은 상황을 가정하면 버퍼 풀에 더티 페이지가 계속해서 쌓이게 될 것이고, InnoDB가 기본적으로 가질 수 있는 버퍼 풀의 더티 페이지 비율인 90%를 넘어간다면, 더티 페이지를 디스크에 동기화하는 작업이 폭증할 것이다. InnoDB에서는 시스템 설정을 사용하여 일정 수준의 더티페이지가 발생하면 더티 페이지를 조금씩 디스크로 기록하도록 동작하고 있다.
버퍼 풀의 크기에 대한 <Real MySQL 8.0 1>의 의견
운영체제의 전체 메모리 공간이 8GB 미만이라면 50% 정도만 InnoDB 버퍼 풀로 설정하고 나머지 메모리 공간은 MySQL 서버와 운영체제, 그리고 다른 프로그램이 사용할 수 있는 공간으로 확보해주는 것이 좋다. 전체 메모리 공간이 그 이상이라면 InnoDB 버퍼 풀의 크기를 전체 메모리의 50%에서 시작해서 조금씩 올려가면서 최적점을 찾는다.
'Database > Real MySQL' 카테고리의 다른 글
MySQL 엔진과 InnoDB 엔진의 잠금 (1) | 2024.01.27 |
---|---|
트랜잭션(Transaction)과 격리 수준(Isolation level) (1) | 2024.01.27 |
InnoDB 스토리지 엔진 - 지원 기능 (1) | 2024.01.26 |
쿼리 실행 구조와 MySQL 8.0 변경점 (2) | 2024.01.25 |
MySQL 아키텍처와 스레딩 (2) | 2024.01.25 |