DBMS/MySQL

[Real MySQL] 3장(2). 아키텍처 - InnoDB 스토리지 엔진 아키텍처

반응형

2. InnoDB 스토리지 엔진 아키텍처

InnoDB는 MySQL에서 사용할 수 있는 스토리지 엔진 중에서 거의 유일하게 레코드 기반의 잠금을 제공하고 있어서 높은 동시성 처리가 가능하고 안정적이며 성능이 뛰어나다.

 

InnoDB 스토리지 엔진의 특성

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

  • 프라이머리 키 값의 순서대로 디스크에 저장된다는 뜻
  • 프라이머리 키에 의한 레인지 스캔은 상당히 빨리 처리될 수 있음

 

잠금이 필요 없는 일관된 읽기

  • MVCC 기술을 이용해 락을 걸지 않고 읽기 작업을 수행.

 

외래 키 지원

  • 외래 키에 지원은 InnoDB 스토리지 엔진 레벨에서 지원하는 기능으로, MyISAM이나 Memory 테이블에서는 사용할 수 없음.
  • 여러 가지 제약사항 탓에 실무에서는 잘 사용하지 않기 때문에 그렇게 필수적이지는 않음.

InnoDB 버퍼 풀

  • 디스크의 데이터 파일이나 인덱스 정보를 메모리에 캐시 해두는 공간
  • 쓰기 작업을 지연시켜 일괄 작업으로 처리할 수 있게 해주는 버퍼 역할도 수행.

 

더티 페이지

  • InnoDB 버퍼 풀은 아직 디스크에 기록되지 않은 변경된 데이터를 가지고 있다. (더티 페이지라고 한다)
  • 이러한 더티 페이지는 InnoDB에서 주기적으로 또는 특정 조건 시 체크포인트 이벤트가 발생하는데, 이때 Write 스레드가 필요한 만큼의 더티 페이지만 디스크로 기록한다.

언두(Undo) 로그

UPDATE, DELETE와 같은 문장으로 데이터를 변경했을 때 변경되기 전의 데이터를 보관하는 곳.

UPDATE member SET name = '강승호' WHERE member_id = 1;

 

다음 문장이 실행되면 트랜잭션을 커밋하지 않아도 실제 데이터 파일 내용은 '강승호'로 변경된다.

그리고 변경되기 전의 값이 'Will'였다면 언두 영역에는 'Will'라는 값이 백업되는 것이다.

 

이 상태에서 만약에 사용자가 커밋하게 되면 현재 상태가 그대로 유지되고, 롤백하게 되면 언두 영역의 백업된 데이터를 다시 데이터 파일로 복구한다.

언두 데이터의 용도 정리

  • 위와 같이 트랜잭션 롤백 대비용.
  • 트랜잭션의 격리 수준을 유지하면서 높은 동시성을 제공. (차후 트랜잭션 격리 수준과 언두의 용도는 차후 설명)

인서트 버퍼

레코드가 INSERT 되거나 UPDATE 될 때는 데이터 파일을 변경하는 작업뿐 아니라 해당 테이블에 포함된 인덱스를 업데이트하는 작업도 필요. 그런데 인덱스를 업데이트하는 작업은 랜덤 하게 디스크를 읽는 작업이 필요하므로 테이블에 인덱스가 많다면 이 작업은 상당히 많은 자원을 소모하게 된다.

 

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

 

주의사항

  • 결과를 전달하기 전에 반드시 중복 여부를 체크해야 하는 유니크 인덱스는 인서트 버퍼를 사용할 수 없다.
  • 인서트 버퍼에 임시로 저장돼 있는 인덱스 레코드 조각은 이후 백그라운드 스레드에 의해 병합된다.

리두(Redo) 로그 및 로그 버퍼

쿼리 문장으로 데이터를 변경하고 커밋하면 DBMS는 데이터의 ACID를 보장하기 위해 즉시 변경된 데이터의 내용을 데이터 파일로 기록해야 한다. 하지만 이러한 데이터 파일의 변경 작업은 순차적으로 많은 데이터를 한꺼번에 변경하는 것이 아니고 랜덤 하게 디스크에 기록해야 하기 때문에 디스크를 상당히 바쁘게 만드는 작업이다.

 

그래서 이러한 부하를 줄이기 위해 InnoDB 버퍼 풀과 같은 장치가 포함되어 있는데, 이 장치만으로는 ACID를 보장할 수 없는데 이를 위해 변경된 내용을 순차적으로 디스크에 기록하는 로그 파일을 가지고 있다. (리두 로그)


MVCC (Multi Version Concurrency Control)

  • 일반적으로 레코드 레벨 트랜잭션을 지원하는 DBMS가 제공하는 기능
  • MVCC의 가장 큰 목적은 잠금을 사용하지 않는 일관된 읽기를 제공.
  • InnoDB는 언두 로그를 이용해 이 기능을 구현한다.

기존의 테이블에 id =1, name = '강승호'라는 데이터가 있을 때, 다음과 같은 쿼리 문장이 실행되면

UPDATE member SET name = 'will' WHERE id = 1;
  • InnoDB 버퍼 풀: UPDATE 문장이 실행되면 커밋 실행 여부와 관계없이, InnoDB의 버퍼 풀은 새로운 값인 'will'로 업데이트된다.
  • 디스크의 데이터 파일: 체크포인트나 InnoDB의 Write 스레드에 의해 새로운 값으로 업데이트돼 있을 수도 있고 아닐 수도 있음.
  • Undo 로그: 변경 전의 데이터인 '강승호'로 저장.

 

Q) 아직 커밋이나 롤백되지 않은 상태에서 다른 사용자가 다음과 같은 쿼리로 작업 중인 레코드를 조회하면 어디에 있는 데이터를 조회할까?

SELECT * FROM member WHERE id = 1;

 

답은, 격리 수준에 따라 다르다.

 

READ_UNCOMMITTED의 경우

  • InnoDB 버퍼 풀이나 데이터 파일로부터 변경되지 않은 데이터를 읽어서 반환.

 

READ-COMMITTED나 그 이상의 격리 수준

  • 이전 내용을 보관하고 있는 언두 영역의 데이터를 반환

 

이 상태에서 커밋 명령을 실행하면

  • InnoDB는 더 이상의 변경 작업 없이 지금의 상태를 영구적인 데이터로 만들어 버린다.

 

반면 롤백을 실행하면

  • InnoDB는 언두 영역에 있는 백업된 데이터를 InnoDB 버퍼 풀로 다시 복구하고, 언두 영역의 내용을 삭제한다.

잠금 없는 일관된 읽기

InnoDB에서 격리 수준이 SERIALIZABZLE이 아닌 READ-UNCOMMITED, READ_COMMITED, REPEATABLE-READ 수준인 경우, INSERT와 연결되지 않은 순수한 SELECT 작업은 다른 트랜잭션의 변경 작업과 관계없이 항상 잠금을 대기하지 않고 바로 실행된다.

 

즉, 특정 사용자가 레코드를 변경하고 아직 커밋을 수행하지 않았다 하더라도 이 변경 트랜잭션이 다른 사용자의 SELECT 작업을 방해하지 않는다. ⇒ 잠금 없는 일관된 읽기

 

InnoDB에서는 이를 위해 Undo 로그를 사용한다.


3. MEMORY 스토리지 엔진 아키텍처

  • MEMORY 스토리지 엔진은 HEAP 스토리지 엔진이라고도 하며, 데이터를 메모리 저장하는 것이 특징.
  • MEMORY 스토리지 엔진은 데이터의 크기가 작고 아주 빠른 처리가 필요한 경우에만 적합한 스토리지 엔진이다.
  • 기본적으로 해시 인덱스를 사용
  • MEMORY 테이블은 주로 MySQL 엔진이 쿼리를 처리하는 과정에서 임시로 생성되는 임시 테이블의 용도로 자주 사용된다. (임시 테이블은 해당 커넥션에서만 유효)

MySQL 로그파일의 종류

  • 에러 로그 파일
  • 제너럴 쿼리 로그 파일
  • 슬로우 쿼리 로그: 서비스에서 사용되고 있는 쿼리 중에서 어떤 쿼리가 문제인지 판단하는데 슬로우 쿼리 로그가 상당히 많은 도움이 된다.
  • 바이너리와 릴레이 로그: 앞서 말했듯이, 복제를 위해 사용됨.

 

반응형