[REALMYSQL] 4.2 InnoDB 스토리지 엔진 아키텍처

Minseok-Choi·2022년 5월 17일
0

realmysql

목록 보기
2/3

학습자료

  • 백은빈, 이성욱 RealMySql 8.0 1

InnoDB 스토리지 엔진 아키텍처

  • InnoDB는 MySql 기본 스토리지 엔진

주요 특징

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

  • InnoDB의 모든 테이블은 기본적으로 PK를 기준으로 클러스터링되어서 저장된다. (클러스터드 인덱스)
    • PK 값 순서대로 디스크에 저장된다는 의미
    • 세컨더리 인덱스(논클러스터드 인덱스)는 PK 값을 논리적 주소로 사용

2. 외래 키 지원

  • InnoDB에서의 외래키
    • 부모 테이블, 자식 테이블 모두 해당 칼럼에 대한 인덱스 생성이 필요함
    • 변경 시에는 반드시 부모 또는 자식 테이블에 데이터가 있는지 확인하는 작업이 필요함
      • 이에 따라서 잠금이 여러 테이블로 전파, 데드락 발생 가능성이 높아짐
  • 이러한 이유로, 외래 키의 존재는 개발할 때 조심해야함

3. MVCC (Multi Version Concurrency Control)

  • 레코드 레벨의 트랜잭션을 지원하는 기능
  • 잠금을 사용하지 않는 일관적 읽기를 제공하는 것이 목적
  • InnoDB에서는 언두 로그를 통해서 기능을 구현
  • 격리 수준에 따라서 사용자에게 제공하는 데이터의 버전이 달라짐
  • 트랜잭션이 길어지면 언두에서 관리하는 예전 데이터(버전)가 오랫동안 관리되는 상황이 발생 -> 성능 저하
    • 최대한 트랜잭션을 짧게 가져가는 것이 중요
  • 언두 영역의 백업데이터는 더 이상 필요로하는 트랜잭션이 없을 때 삭제됨

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

  • 격리 수준이 SERIALIZABLE이 아니라면 순수한 읽기 작업은 잠금을 대기하지 않고 실행됨

5. 자동 데드락 감지

  • 잠금 대기 목록을 그래프 형태로 관리(Wait-for List)
  • 데드락 감지 스레드를

6. 자동화된 장애 복구

  • 손실이나 장애로부터 데이터를 보호하기 위한 여러가지 메커니즘이 탑재
  • MySQL 서버가 실행될 때, 완료되지 못한 트랜잭션이나 partial write 데이터 페이지에 대해서 복구 작업을 자동으로 실행

InnoDB 버퍼 풀

  • 가장 핵심적인 부분
  • 디스크의 데이터 파일, 인덱스 정보를 메모리에 캐시해두는 곳
  • 쓰기 지연을 처리해주는 버퍼 역할
    • 쓰기 지연을 통해서 랜덤한 디스크 작업의 횟수를 줄인다.
  • 5.7 버전부터 버퍼 풀의 크기를 동적으로 조절할 수 있게 개선되었음
    • 적절히 작은 값으로 설정해서 조금씩 증가시키는 방법이 좋다.
    • 버퍼 풀의 크기를 작게 조정하는 것은 서비스 영향도가 매우 크다.
    • 128MB 청크 단위로 쪼개서 관리되는데 크기를 조정하는 단위 크기로 사용된다.

버퍼 풀의 구조

  • 버퍼 풀의 페이지 크기 조각을 관리하기 위해서 LRU 리스트, Flush 리스트, Free 리스트 3개의 자료 구조를 관리한다.
    • Free 리스트 : 비어 있는 페이지들의 목록
    • LRU 리스트 : LRU와 MRU 리스트가 결합된 형태
      • Old 서브리스트 : LRU
      • New 서브리스트 : MRU
      • LRU 리스트를 관리하는 목적은 한번 읽어온 페이지를 최대한 메모리에 유지해서 디스크 읽기를 최소화하는 것
    • Flush 리스트 : 더티 페이지 목록을 관리
      • 더티 페이지는 특정 시점에 디스크에 기록
      • 데이터가 변경되면 리두 로그에 기록, 버퍼 풀의 데이터 페이지에도 변경 내용을 반영

스토리지 엔진이 데이터를 찾는 과정

  1. 필요한 레코드가 저장된 데이터 페이지가 버퍼 풀에 있는지 검사

    a. 어댑티브 해시 인덱스를 이용해서 페이지를 검색

    b. 테이블의 인덱스(B-Tree)를 이용해서 버퍼 풀에서 페이지를 검색

    c. 버퍼 풀에 데이터 페이지가 있었다면, 포인터를 MRU 방향으로 승급

  2. 디스크에서 필요한 데이터 페이지를 버퍼 풀에 적재, 포인터를 LRU 헤더 부분에 추가

  3. LRU 헤더 부분에 적재된 페이지가 읽히면, MRU 헤더 부분으로 이동

  4. 버퍼 풀에 상주하는 데이터 페이지는 age가 부여되며, 너무 오래된 페이지는 삭제되고 다시 사용되면 age 초기화

  5. 자주 접근된 페이지는 인덱스 키를 어댑티브 해시 인덱스에 추가

버퍼 풀과 리두 로그

  • 버퍼 풀의 메모리 공간을 크게 만들면, 데이터 캐시 기능만 성능 향상
  • 쓰기 버퍼링 기능의 성능 향상을 위해서는 버퍼 풀의 리두 로그 관계를 이해해야 함

조금 더 이해하고 정리하기로..

버퍼 풀 플러시

  • 더티 페이지 플러시(더티 페이지를 디스크에 동기화하는 것)
  • 2개의 플러시 기능을 백그라운드로 실행
    • Flush 리스트 플러시
    • LRU 리스트 플러시

플러시 리스트 플러시

  • 클리너 스레드 : 더티 페이지를 디스크로 동기화하는 스레드
    • innodb_pate_cleanersinnodb_buffer_pool_instances설정을 동일하게 맞춰주자 (인스턴스 당 스레드를 하나씩!)
  • 기본적으로 버퍼 풀에 있는 페이지의 90%까지 더티 페이지로 가지고 있을 수 있음
    • 하지만 이렇게 되면 디스크 I/O 폭증 현상(Disk IO Burst) 발생
    • innodb_max_dirty_pags_lwm : 일정 수준의 더티 페이지가 생기면 조금씩 디스크로 기록하도록 하는 변수
      • 기본적으로 10%, 디스크 쓰기가 많고, 더티 페이지 비율이 낮다면 변수를 높게 조정

LRU 리스트 플러시

  • LRU 리스트에서 사용 빈도가 낮은 데이터 페이지들을 제거
  • LRU 리스트 끝부분부터 innodb_lru_scan_depth에 설정된 갯수만큼 페이지 스캔
    • 더티 페이지는 디스크 동기화, 클린 페이지는 Free 리스트로 옮김
    • 인스턴스마다 페이지 스캔 -> 인스턴스 갯수 * 설정된 페이지 갯수 스캔

버퍼 풀 상태 백업 및 복구

  • 버퍼 풀 덤프 및 적재 기능

    • Innodb_buffer_dump_now 시스템 변수를 이용해 백업 가능
    • innodb_buffer_pool_load_now 변수를 이용해서 상태를 다시 복구할 수 있음
  • 버퍼 풀 백업은 데이터 디렉토리에 ib_buffer_pool 이라는 파일로 생성

    • 메타 정보만을 백업

Double Write Buffer

  • 리두 로그는 변경된 내용만 기록
    • 더티 페이지를 플러시할 때, Partial-page, Torn-page 현상 발생 가능 -> 복구 불가능
  • Double-Write 기법을 이용
    • 더티 페이지를 묶어서 한 번의 디스크 쓰기로 시스템 테이블스페이스의 더블라이트 버퍼에 기록

언두 로그

  • 트랜잭션과 격리 수준을 보장하기 위해서 백업 -> 언두 로그

더 이해하고 정리

체인지 버퍼

  • 레코드가 insert 혹은 update 되면 데이터 파일 변경 및 인덱스 변경 작업이 필요하다.
  • 인덱스 업데이트는 랜덤하게 디스크를 읽는 작업이 필요해서 성능 향상을 위해서 체인지 버퍼에 저장해둔다.
    • 유니크 인덱스는 체인지 버퍼를 사용할 수 없다.
    • 인덱스 레코드 조각은 체인지 버퍼 머지 스레드에 의해서 병합된다.

리두 로그

  • 하드웨어나 소프트웨어 등 여러 가지 문제로 인해서 MySQL 서버가 비정상적으로 종료했을 때, 기록되지 못한 데이터를 잃지 않도록 하는 역할
    • MySQL을 포함해서 대부분의 데이터베이스 서버는 데이터 변경 내용을 로그로 먼저 기록한다.
    • 일부 DBMS에서는 Write Ahead Log(WAL)이라고도 부른다.
  • 커밋됐지만 데이터 파일에 기록되지 않은 데이터 -> 리두 로그 내용을 통해서 데이터 파일에 복사
  • 롤백됐지만 데이터 파일에 이미 기록된 데이터 -> 언두 로그 내용을 복사해서 해결 (리두 로그에서 커밋, 롤백, 트랜잭션 상태를 알기위해서 필요)
  • 변경 작업이 많은 DBMS 서버의 경우 리두 로그 기록 작업이 문제가 된다.
    • 최대한 ACID 속성을 보장하는 수준으로 버퍼링 하게 된다. -> 버퍼링에 사용되는 공간이 로그 버퍼

어댑티브 해시 인덱스

  • 사용자가 수동으로 생성하는 인덱스가 아니라 innoDB가 사용자가 자주 요청하는 데이터에 대해서 자동으로 생성하는 인덱스
  • B-Tree 검색 시간을 줄이기 위해서 도입된 기능
  • 데이터 페이지의 키 값을 이용해서 해시 인덱스를 만들고, 어댑티브 해시 인덱스를 검색해서 레코드가 저장된 데이터 페이지를 즉시 찾아갈 수 있도록 한 것
profile
차곡차곡

0개의 댓글