티스토리 뷰

InnoDB 스토리지 엔진 아키텍처 1InnoDB 스토리지 엔진 아키텍처 2는 여기에서 살펴보실 수 있습니다.


Double Write Buffer


InnoDB 스토리지 엔진에서는 더티 페이지를 디스크 파일로 플러시할 때, 일부만 기록되는 문제를 막기 위해 Double-Write 기법을 이용한다.

아래 그림은 InnoDB에서 "A" ~ "E"까지의 더티 페이지를 디스크로 플러시하는 상황이다.
InnoDB의 스토리지 엔진은 실제 데이터 파일에 변경 내용을 기록하기 전에 "A" ~ "E"까지의 더티 페이지를 우선 묶어서 한 번의 디스크 쓰기로 시스템 테이블스페이스의 DoubleWrite 버퍼에 기록하고, 각 더티 페이지를 파일의 적당한 위치에 하나씩 랜덤으로 쓰기를 실행한다.



InnoDB 스토리지 엔진은 재시작될 때, 항상 DoubleWrite 버퍼의 내용과 데이터 파일의 페이지들을 모두 비교해서 다른 내용의 페이지가 있으면 DoubleWrite 버퍼의 내용을 데이터 파일의 페이지로 복사하기 때문에 운영체제가 중간에 비정상적으로 종료되더라도 데이터를 안정성을 보장할 수 있다.


언두 로그


InnoDB 스토리지 엔진은 트랜잭션과 격리 수준을 보장하기 위해 DML(INSERT, UPDATE, DELETE)로 변경되기 이전 버전의 데이터를 별도로 보관하는데, 이를 언두 로그(Undo Log)라고 한다.


트랜잭션 보장
트랜잭션이 롤백되면 트랜잭션 도중 변경된 데이터를 변경 전 데이터로 복구해야 하는데, 이때 언두 로그에 백업해둔 이전 버전의 데이터를 이용하여 복구한다.


격리 수준 보장
특정 커넥션에서 데이터를 변경하는 도중에 다른 커넥션에서 데이터를 조회하면 트랜잭션 격리 수준에 맞게 변경 중인 레코드를 읽지 않고, 언두 로그에 백업해둔 데이터를 읽어서 변환하기도 한다.


언두 로그는 InnoDB 스토리지 엔진에서 매우 중요한 역할을 담당하는만큼 많은 관리 비용이 필요하다.


언두 로그 모니터링

트랜잭션이 완료됐다고 해서 해당 트랜잭션이 생성한 언두 로그를 즉시 삭제할 수 있는 것은 아니며, MySQL 5.5 이전 버전에서는 한 번 증가된 언두 로그 공간은 새로 구축하지 않는 이상 그 공간의 크기를 줄일 수 없었다.


MySQL 8.0에서는 언두 로그를 돌아가면서 순차적으로 사용해 디스크 공간을 줄이는 것도 가능하며, 때로는 MySQL 서버가 필요한 시점에 사용 공간을 자동으로 줄여 주기도 하면서 언두 로그 공간의 문제점은 완전히 해결됐다.


언두 테이블스페이스 관리

언두 로그가 저장되는 공간을 언두 테이블스페이스(Undo Tablespace)라고 하며, MySQL 5.6 이전 버전에서는 언두 로그가 모두 시스템 테이블스페이스에 저장됐다. 하지만 시스템 테이블스페이스의 언두 로그는 MySQL 서버가 초기화될 때 생성되기 때문에 확장의 한계가 있었다.


MySQL 8.0으로 업그레이드되면서(MySQL 8.0.14 버전부터) 언두 로그는 항상 시스템 테이블스페이스 외부의 별도 로그 파일에 기록되도록 개선됐다.


체인지 버퍼


레코드가 INSERT되거나 UPDATE될 때는 데이터 파일을 변경하는 작업뿐 아니라 해당 테이블에 포함된 인덱스를 업데이트하는 작업도 필요하다.


InnoDB는 변경해야 할 인덱스 페이지가 버퍼 풀에 있으면 바로 업데이트를 수행하지만, 디스크로부터 읽어와서 업데이트해야 한다면 이를 즉시 실행하지 않고 임시 공간에 저장해두고 바로 사용자에게 결과를 반환하는 형태로 성능을 향상시키게 되는데, 이때 사용하는 임시 메모리 공간을 체인지 버퍼(Change Buffer)라고 한다.


MySQL 5.5부터는 innodb_change_bufferring이라는 시스템 변수가 새로 도입되어 작업의 종류별로 체인지 버퍼를 활성화할 수 있으며, 체인지 버퍼가 비효율적일 때는 체인지 버퍼를 사용하지 않게 설정할 수 있게 개선되었다.


아래는 innodb_change_bufferfing 시스템 변수에 설정할 수 있는 값이다.

  • all: 모든 인덱스 관련 작업(inserts + deletes + purges)을 버퍼링
  • none: 버퍼링 X
  • inserts: 인덱스에 새로운 아이템을 추가하는 작업만 버퍼링
  • deletes: 인덱스에서 기존 아이템을 삭제하는 작업(삭제됐다는 마킹 작업)만 버퍼링
  • changes: 인덱스에 추가하고 삭제하는 작업만(inserts + deletes) 버퍼링
  • purges: 인덱스 아이템을 영구적으로 삭제하는 작업만 버퍼링(백그라운드 작업)

리두 로그 및 로그 버퍼


리두 로그는 하드웨어나 소프트웨어에서 여러 가지 문제점으로 인해 MySQL 서버가 비정상적으로 종료됐을 때, 데이터 파일에 기록되지 못한 데이터를 잃지 않게 해주는 안전장치다.


MySQL 서버가 비정상 종료되는 경우 InnoDB 스토리지 엔진의 데이터 파일은 다음과 같은 두 가지 종류의 일관되지 않은 데이터를 가질 수 있다.

  1. 커밋됐지만, 데이터 파일에 기록되지 않은 데이터
  2. 롤백됐지만, 데이터 파일에 이미 기록된 데이터

1번의 경우 리두 로그에 저장된 데이터를 데이터 파일에 다시 복사하기만 하면된다. 하지만 2번의 경우에는 리두 로그로는 해결할 수 없는데, 이때는 변경되기 전 데이터를 가진 언두 로그의 내용을 가져와 데이터 파일에 복사하면 된다. 그렇다고 해서 2번의 경우 리두 로그가 전혀 필요하지 않은 것은 아니다. 최소한 그 변경이 커밋됐는지, 롤백됐는지, 아니면 트랜잭션의 실행 중간 상태였는지를 확인하기 위해서라고 리두 로그가 필요하다.


데이터베이스 서버에서 리두 로그는 트랜잭션이 커밋되면 즉시 디스크로 기록되도록 시스템 변수를 설정하는 것을 권장한다.


어댑티브 해시 인덱스


어댑티브 해시 인덱스는 사용자가 수동으로 생성하는 인덱스가 아니라 InnoDB 스토리지 엔진에서 사용자가 자주 요청하는 데이터에 대해 자동으로 생성하는 인덱스이며, innodb_adaptive_hash_index 시스템 변수를 이용해서 어댑티브 해시 인덱스 기능을 활성화하거나 비활성화할 수 있다.


어댑티브 해시 인덱스는 B-Tree 검색 시간을 줄여주기 위해 도입된 기능으로 InnoDB 스토리지 엔진은 자주 읽히는 데이터 페이지의 키 값을 이용해 해시 인덱스를 만들고, 필요할 때마다 어댑티브 해시 인덱스를 검색해서 레코드가 저장된 데이터 페이지를 즉시 찾아갈 수 있다. B-Tree를 루트 노트로부터 리프 노드까지 찾아가는 비용이 없어지고, 쿼리의 성능은 빨라진다.


어댑티브 해시 인덱스가 성능 향상에 크게 도움이 되지 않는 이유는 아래와 같다.

  • 디스크 읽기가 많은 경우
  • 특정 패턴의 쿼리가 많은 경우(조인이나 LIKE 패턴 검색)
  • 매우 큰 데이터를 가진 테이블의 레코드를 폭넓게 읽는 경우

반면, 아래와 같은 경우에는 성능 향상에 많은 도움이 된다.

  • 디스크의 데이터가 InnoDB 버퍼 풀 크기와 비슷한 경우(디스크 읽기가 많지 않은 경우)
  • 동등 조건 검색(동등 비교와 IN 연산자)이 많은 경우
  • 쿼리가 데이터 중에서 일부 데이터에만 집중되는 경우

InnoDB와 MyISAM, MEMORY 스토리지 엔진 비교


MySQL 8.0으로 업그레이드되면 MySQL 서버의 모든 시스템 테이블이 InnoDB 스토리지 엔진으로 교체됐고, 공간 좌표 검색이나 전문 검색 기능이 모두 InnoDB 스토리지 엔진을 지원하도록 개선됐다.


InnoDB 스토리지 엔진에 대한 기능이 개선되는 만큼 MyISAM 스토리지 엔진이나 MEMORY 스토리지 엔진은 도태되고 있는 상황이기 때문에, 이후 버전에서는 MyISAM 스토리지 엔진과 MEMORY 스토리지 엔진 모두 없어질 것으로 예상되고 있다.




요약

  • InnoDB 스토리지 엔진은 Double Write Buffer 버퍼를 이용해서 비정상적인 종료로부터 데이터의 안정성을 보장한다.
  • MySQL 8.0에서는 언두 로그를 돌아가며 순차적으로 사용해서 디스크 공간을 줄일 수 있고, 사용 공간이 자동으로 줄기도 하며, 언두 로그를 항상 시스템 테이블스페이스 외부의 별도 로그 파일에 기록하도록 개선됐다.
  • MySQL은 빠른 속도를 위해 체인지 버퍼를 이용하여 INSERT 또는 UPDATE 후의 내용을 먼저 반환하고, INSERT 또는 UPDATE작업을 처리한다.
  • 리두 로그는 MySQL 서버가 비정상 종료됐을 때, 데이터 파일에 기록되지 못한 데이터를 잃지 않게 해주는 안전장치다.
  • 어댑티브 해시 인덱스는 자주 읽히는 데이터 페이지의 키 값을 이용해서 해시 인덱스를 만들고, 필요할 때마다 레코드가 저장된 데이터 페이지를 즉시 찾아간다.
  • MySQL 8.0 버전 이후부터는 MySQL 서버의 모든 시스템 테이블이 InnoDB 스토리지 엔진으로 교체되었다.



Reference
백은빈, 이성욱. 『Real MySQL 8.0』. 위키북스, 2022

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함