티스토리 뷰
개발자와 DBA를 위한 Real MySQL을 읽고 정리한 내용입니다. 그중에서 현재 사용하고 있는 InnoDB 스토리지 엔진에 대해 알아보고자 공부하고, 정리하게 되었습니다. 우선 InnoDB 스토리지 엔진의 가장 큰 특징은 다음과 같습니다.
- 레코드 기반의 잠금 제공
- 레코드 기반의 잠금 덕분에 높은 동시성 처리 가능
- 안정적이며, 성능이 뛰어남
InnoDB 스토리지 엔진의 특성
프라이머리 키에 의한 클러스터링
- 프라이머리 키 값의 순서대로 디스크에 저장된다.
- 프라이머리 키에 의한 Range Scan은 상당히 빨리 처리될 수 있다.
- 쿼리의 실행 계획에서 프라이머리 키는 기본적으로 보조 인덱스에 비해 비중이 높게 설정되어 있다.
잠금이 필요 없는 일관된 읽기
- MVCC(Multi Version Concurrency Control)라는 기술을 이용해 Lock을 걸지 않고, 읽기 작업을 수행한다.
- Lock을 걸지 않기 때문에 InnoDB에서 읽기 작업은 다른 트랜잭션이 가지고 있는 Lock을 기다리지 않는다. (SERIALIZABLE 격리 수준은 제외)
외래 키 지원
- 외래 키 컬럼은 부모 테이블과 자식 테이블에 인덱스 생성이 필요하다.
- 변경 시에는 반드시 부모 테이블이나 자식 테이블에 데이터가 있는지 체크하는 작업이 필요하므로 잠금이 여러 테이블로 전파되고, 이로 인해 데드락이 발생할 때가 많다.
자동 데드락 감지
- 감지된 데드락은 관련 트랜잭션 중에서 Rollback이 가장 용이한 트랜잭션을 자동적으로 강제 종료한다.
자동화된 장애 복구
- 데이터를 보호하기 위한 여러 가지 메커니즘이 탑재돼 있다.
오라클의 아키텍처 적용
- 오라클의 DBMS의 기능과 상당히 비슷한 부분이 많고
- 대표적으로 MVCC 기능이 있다.
- 언두 데이터가 시스템 테이블 스페이스에서 관리된다.
InnoDB 버퍼 풀
- 디스크의 데이터 파일이나 인덱스 정보를 메모리에 캐시 해 두는 공간이다.
- 쓰기 작업을 지연시켜, 일괄 작업으로 처리할 수 있게 해주는 버퍼 역할도 같이 한다.
- 버퍼 풀은 변경된 데이터를 모아서 처리하기 때문에 랜덤한 디스크 작업의 횟수를 줄일 수 있다.
- 데이터와 인덱스를 캐시하고, 쓰기 버퍼링의 역할까지 모두 처리하고 있다.
- 많은 백그라운드 작업의 기반이 되는 메모리 공간이다.
- 아직 디스크에 기록되지 않은 변경된 데이터를 가지고 있는데, 이러한 경우에 InnoDB에서 주기적으로 어떠한 조건으로 인해 이벤트가 발생하면, Write 스레드가 필요한 만큼의 데이터만 디스크로 기록한다.
언두(Undo) 로그
- 기존에 'A' 라는 데이터가 있었고, 이를 'B'로 변경하는 Update 쿼리를 실행하면, 트랜잭션이 커밋되지 않아도 실제 데이터 파일의 내용은 'B'로 변경되며, 'A'는 언두 영역에 백업된다.
- 트랜잭션이 그대로 커밋되면, 현재 상태가 그대로 유지된다.
- 트랜잭션이 롤백하게 되면, 언두 영역의 'A' 데이터를 실제 데이터 파일로 복구한다.
- 트랜잭션의 롤백 대비용이다.
- 트랜잭션의 격리 수준을 유지하면서, 높은 동시성을 제공하는데 사용된다.
Insert 버퍼
- 변경해야 할 인덱스 페이지가 버퍼 풀에 있으면, 바로 업데이트를 수행한다.
- 디스크에서 데이터를 읽고 업데이트 해야 한다면, 이를 즉시 실행하지 않고 임시 공간에 저장해 두고 바로 사용자에게 결과를 반환하는 형태로 성능을 향상한다.
- 사용하는 임시 메모리 공간을 Insert 버퍼라고 한다.
리두(Redo) 로그 및 로그 버퍼
- 데이터의 ACID를 보장하기 위해 즉시 변경된 데이터의 내용을 데이터 파일로 기록해야 하며, 데이터 파일 변경 작업은 랜덤 하게 디스크에 기록해야 하기 때문에 디스크를 상당히 바쁘게 만드는 작업이다.
- 디스크 부하를 줄이기 위해 InnoDB 버퍼 풀과 함께 ACID를 보장하기 위한 변경 내용을 순차적으로 기록하는 로그 파일이 있으며, 이 것이 리두(Redo) 로그이다.
MVCC (Multi Version Concurrency Control)
- 가장 큰 목적은 잠금을 사용하지 않는 일관된 읽기를 제공하는 데 있다.
- 언두 로그를 이용해 이 기능을 구현한다.
- 멀티 버전이라 함은 하나의 레코드에 대해 여러 개의 버전이 동시에 관리된다는 의미이다.
- READ_UNCOMMITTED 격리 수준에서는 InnoDB 버퍼 풀이나 데이터 파일로부터 변경되지 않은 데이터를 읽어서 반환한다.
- READ_COMMITTED, REPEATABLE_READ 격리 수준에서는 변경되기 이전의 내용을 보관하고 있는 언두 영역의 데이터를 반환한다.
- Commit 명령을 실행하면, 지금의 상태를 영구적인 데이터로 만든다.
- Rollback 명령을 실행하면, 언두 영역에 있는 백업된 데이터를 InnoDB 버퍼 풀로 다시 복구하고, 언두 영역의 내용을 삭제한다.
- 언두 영역을 필요로 하는 트랜잭션이 없을 때 비로소 삭제된다.
잠금 없는 일관된 읽기 (Non-Locking Consistent Read)
- READ_COMMITTED, REPEATABLE_READ 격리 수준에서 순수한 읽기의 경우에는 다른 트랜잭션의 변경 작업과 관계없이 항상 잠금을 대기하지 않고, 바로 실행된다.
- 트랜잭션에서 레코드를 변경하고 Commit을 수행하지 않았어도, 다른 트랜잭션의 Select 작업을 방해하지 않는다.
참고
댓글