3. Mysql 아키텍처(3.2, 3.3)
3.2 InnoDB 스토리지 엔진 아키텍처
3.2.1 InnoDB 스토리지 엔진의 특성
PK에 의한 클러스터링
InnoDB의 모든 데이터 테이블은 기본적으로 프라이머리 키를 기준으로 클러스터링 되어 저장된다. 즉 PK값의 순서대로 디스크에 저장된다는 의미이며, 이로 인해 PK에 의한 레인지 스캔은 상당히 빨리 처리될 수 있다.
잠금이 필요없는 일관된 읽기
InnoDB는 MVCC(Multi Version Concurrency Control)라는 기술을 이용해 락을 걸지 않고 읽기 작업을 수행한다.
외래 키 지원
InnoDB에서는 외래키를 지원하지만 실무에서는 여러가지 제약때문에 잘 사용하지 않다. 하지만 데이터베이스의 좋은 가이드 역할로 사용이 가능하다.
자동 데드락 감지
InnoDB는 그래프 기반의 데드락 체크 방식을 사용하기 때문에 데드락이 발생함과 동시에 바로 감지되고, 감지된 데드락은 관련 트랜잭션 중에서 rollback 이 가장 용이한 트랜잭션을 자동적으로 강제 종료해 버린다.
자동화된 장애 복구
오라클의 아키텍처 적용
3.2.2 InnoDB 버퍼 풀
InnoDB 스토리지 엔젠에서 가장 핵심적인 부분으로, 디스크의 데이터 파일이나 인덱스 정보를 메모리에 캐시해 두는 공간이다. MyISAM 키 캐시가 인덱스의 캐시만을 주로 처리하는데 비해 InnoDB의 버퍼 풀은 데이터와 인덱스 모두 캐시하고 쓰기 버퍼링의 역할까지 모두 처리하고 있는 것이다.
3.2.3 Undo 로그
언두 영역은 update, delete와 같은 문장으로 데이터를 변경했을 때 변경되기 전의 데이터를 보관하는 곳이다.
언두의 데이터는 크게 두가지 용도로 사용되는데, 첫 번째가 트랜잭션의 롤백 대비용, 두 번째는 트랜잭션의 격리 수준을 유지하면서 높은 동시성을 제공하는 데 사용된다. 트랜잭션의 격리 수준이라는 개념이 있는데, 이는 동시에 여러 트랜잭션이 데이터를 변경하거나 조회할 때, 한 트랜잭션의 작업 내용이 다른 트랜잭션에 어떻게 보여질지를 결정하는 기준이다.
3.2.4 Insert Buffer
RDBMS에서 레코드가 insert 되거나 update 될때 데이터 파일을 변경하는 작업뿐 아니라 해당 테이블에 포함된 인덱스를 업데이트 하는 작업도 필요하다. 그런 인덱스를 업데이트 하는 작업은 랜덤하게 디스크를 읽는 작업이 필요하므로 테이블에 인덱스가 많다면 이 작업은 상당히 많은 자원을 소모하게 된다. InnoDB는 변경해야 할 인덱스 페이지가 버퍼 풀에 있으면 바로 업데이트를 수행하지만, 그렇지 않고 디스크로 부터 읽어와서 업데이트해야 한다면 이를 즉시 실행하지 않고 임시 공간에 저장해 두고 바로 사용자에게 결과를 반환하는 형태로 성능을 향상시키게 되는데, 이때 사용하는 임시 메모리 공간을 인서트 버퍼(Insert Buffer) 라고 한다.
3.2.5 Redo 로그 및 로그 버퍼
쿼리 문장으로 데이터를 변경하고 커밋하면 DBMS는 데이터의 ACID를 보장하기 위해 즉시 변경된 데이터의 내용을 데이터 파일로 기록해야 한다. 하지만 이런 작업은 랜덤하게 디스크에 기록해야 하므로 디스크를 바쁘게 만드는 작업이다. 그래서 대부분의 DBMS에는 변경된 데이터를 버퍼링해 두기 위해 InnoDB 버퍼 풀과 같은 장치가 포함되어 있다. 하지만 이 장치만으로는 ACID를 보장할 수 없는데 이를 위해 변경된 내용을 순차적으로 디스크에 기록하는 로그 파일을 가지고 있다. 이를 리두 로그 라고 한다.
하지만 사용량이 많은 DBMS 서버의 경우 이 리두 로그의 기록 작업이 큰 문제가 되는데, 이러한 부분을 보완하기 위한 로그 버퍼링이 존재하는데 이 로그 버퍼링에 사용되는 공간이 로그 버퍼 이다.
3.2.6 MVCC(Multi Version Concurrency Control)
MVCC는 잠금을 사용하지 않는 일관된 읽기를 제공하는데 있다. InnoDB에서는 언두 로그를 이용해 이 기능을 구현한다.
update 문장이 실행될 때 기존의 데이터는 언두 로그에 기록되며 새로운 데이터는 InnoDB 버퍼 풀에 기록된다. 즉 하나의 레코드에 대해 두가지 버전의 데이터가 있으며 select문을 이용해 조회를 할 경우 보여지는 데이터는 격리수준에 따라 다르다.
최종적으로 commit 이 되면 레코드의 테이터를 바꾸고, rollback 을 하면 언두 영역에 있는 데이터를 버퍼 풀로 가져온다. 즉 커밋이 된다고 언두 영역의 데이터가 바로 삭제되는게 아니다. 이 언두 영역을 필요로 하는 트랜잭션이 더는 필요 없을 때 비로소 삭제된다.
3.2.7 잠금이 없는 일관된 읽기
특정 사용자가 레코드를 변경하고 아직 커밋을 수행하지 않았다 하더라도 이 변경 트랜잭션이 다른 사용자의 select 작업을 방해하지 않는다. 이를 잠금이 없는 일관된 읽기 라고 표현하며 InnoDB에서는 언두 로그를 사용하여 구현한다.
3.3 MyISAM 스토리지 엔진 아키텍처
3.3.1 키 캐시
InnoDB의 버퍼 풀과 비슷한 역할을 하는 것이 MyISAM의 키 캐시다. 하지만 키 캐시는 인덱스만 대상으로 작동하며 인덱스의 디스크 쓰기 작업에 대해서만 부분적으로 버퍼링 역할을 한다.
3.3.2 운영체제의 캐시 및 버퍼
MyISAM 테이블의 인덱스는 키 캐시를 이용해 디스크를 검색하지 않고도 충분히 빠르게 검색할 수 있다. 하지만 MyISAM 테이블의 데이터는 디스크로부터의 I/O를 해결해 줄 만한 어떠한 캐시나 버퍼링 기능이 없다. 그래서 운영체제의 디스크 읽기/쓰기 작업으로 요청될 수 밖에 없다. 운영체제의 캐시 기능은 InnoDB 같이 데이터의 특성을 알고 전문적으로 캐시나 버퍼링을 하지는 못하지만 그래도 없는 것 보다는 낫다. 운영체제의 캐시 공간은 남는 메모리를 사용하는 것이 기본 원칙이다.