Notice
Recent Posts
Recent Comments
Link
«   2024/09   »
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
Tags
more
Archives
Today
Total
관리 메뉴

forDevLife

InnoDB 스토리지 엔진 아키텍처 1 본문

Database

InnoDB 스토리지 엔진 아키텍처 1

JH_Lucid 2022. 5. 12. 13:36

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

 

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


InnoDB의 모든 테이블은 기본적으로 프라이머리 키를 기준으로 클러스터링되어 저장된다. 

  • 즉, 프라이머리 키 값의 순서대로 디스크에 저장된다.
  • 모든 세컨더리 인덱스는 물리적인 레코드의 주소(ROWID) 대신 프라이머리 키의 값을 논리적인 주소로 사용한다. 
  • 결과적으로 쿼리 실행 계획에서 프라이머리 키는 기본적으로 다른 보조 인덱스에 비해 비중이 높게 설정된다.

반면 MyISAM 스토리지 엔진에서는 클러스터링 키를 지원하지 않아, 프라이머리 키와 세컨더리 인덱스는 구조적으로 아무런 차이가 없다. 

  • 프라이머리 키는 유니크 제약을 가진 세컨더리 인덱스일 뿐이다.
  • (프라이머리 키를 포함한) 모든 인덱스는 물리적인 레코드의 주소(ROWID)를 가진다.

 

인덱싱에 대해서는 추후 더 자세하게 알아보자.

 

 

2. 외래 키(제약) 지원


이 역시 InnoDB 엔진에서만 지원하는 기능이었다..!

데이터베이스 서버 운영의 불편함으로 인해 서비스용 데이터베이스에서는 생성하지 않는 경우도 자주 있다고 하는데, 아직은 없는 상황을 상상할 수가 없다. 정확히는 외래 키 제약조건을 걸어준다는 의미이다.

 

외래 키 제약조건(Foreign key constraint)
두 테이블간의 관계를 선언하여 데이터간 무결성을 보장해주는 역할을 한다. 즉, 한쪽이 다른쪽 테이블에 의존하는 형태가 된다.
외래 키 테이블이 참조하는 테이블의 열은 반드시 primary이거나 unique 제약 조건이 설정되어 있어야 한다.

 

제약 조건을 걸게 되면 수동으로 데이터를 적재하거나 스키마 변경 등의 관리 작업이 실패할 수 있다. 부모와 자식 테이블의 관계를 명확히 파악하여 순서대로 작업한다면 문제없이 실행될 수 있지만, 외래키가 복잡하게 얽혀있는 경우에는 파악하기가 쉽지 않다.

이 경우에는 foreign_key_check 시스템 변수를 off로 설정하여, 외래 키 관계 체크 작업을 일시적으로 멈출 수 있다.

※ 참고로 이 옵션을 해제한 경우, ON DELETE CASCADE, ON UPDATE CASCADE 옵션도 무시된다.

mysql> SET foreign_key_checks=OFF;

~~ // 작업 실행

mysql> SET foreign_key_checks=ON;

하지만 이 과정은 데이터의 무결성 체크를 잠시 해제한 경우이기 때문에 반드시 부모와 자식 테이블의 데이터를 각각 수정해서 일관성을 맞춘 후에 외래키 체크를 활성화해야 한다. 

 

 

3. MVCC(Multi Version Concurrency Control)


레코드 레벨의 트랜잭션을 지원하는 DBMS가 지원하는 기능이며, 큰 목적은 잠금을 사용하지 않는 일관된 읽기를 제공하는 데 있다.

InnoDB에서는 언두 로그를 이용하여 이 기능을 구현한다.

언두로그는 최초에 디스크에서 데이터를 읽어 버퍼 풀에 둔 상태에서 Update가 발생하면, 실질적으로 변경된 column에 대해 변경 전의 데이터를 저장하는 공간이라고 생각하면 된다. 하나의 레코드에 대해 이러한 변경 사항이 여러 번 발생할 경우 언두 로그에도 여러 데이터가 쌓이게 되므로 이를 멀티 버전이라고 표현하였다.

 

이해를 위해서 우선 격리수준(Isolation level)에 대해 학습할 필요가 있다. 격리 수준은 아래에 나열된 순서대로 높아지게 되며, 높을 수록 데이터 일관성을 위해 제약이 더 강해지게 된다.

격리 수준에 대한 자세한 내용보다는, 언두 로그의 데이터 사용 여부로만 정리하였다.

 

상황

a. 두 트랜잭션(A, B)이 있다고 가정하자.

b. A 트랜잭션에서 1번 레코드에 대해 변경을 가하고 커밋을 하지 않았다. (이 과정에서 변경 전 데이터를 언두 로그에 기록한다.)

 

1) 격리 수준이 READ_UNCOMMITTED 일 경우,

  • B 트랜잭션에서 1번 레코드의 데이터를 읽는다. 이 때 b.에서 A 트랜잭션이 커밋을 하지 않은 데이터를 그대로 읽어오게 된다.
    ※ 문제점 : A 트랜잭션 중 오류로 인한 롤백이 발생할 경우, B 트랜잭션에서 읽은 값은 무효가 된다. 이 현상을 dirty read라고 한다.

 

2) 격리 수준이 READ_COMMITTED & REPEATABLE_READ & SERIALIZABLE 일 경우,

  • B 트랜잭션에서 1번 레코드의 데이터를 읽어올 때, 아직 b.에서 커밋하지 않았으므로 이전의 내용인 언두 영역의 데이터를 반환한다. 

 

앞선 상황에서 A 트랜잭션에 COMMIT이 실행되면 InnoDB는 더 이상의 변경 작업 없이 지금 상태를 영구적인 데이터로 만들기 위해 버퍼 풀의 내용을 디스크로 반영한다. 하지만 롤백을 실행하면 InnoDB는 언두 영역의 데이터를 버퍼 풀로 다시 복구하고, 언두 영역의 내용을 즉시 삭제한다. 즉 커밋이 된다고 언두 영역의 백업 데이터가 바로 삭제되는 게 아니고, 이 영역을 필요로 하는 트랜잭션이 더 이상 없을 때 비로소 삭제가 발생한다.

 

 

4. 자동화된 장애 복구


InnoDB에는 손실이나 장애로부터 데이터를 보호하기 위한 여러 기능이 탑재되어있다. 이를 통해 MySQL 서버가 시작될 때 완료되지 못한 트랜잭션이나 디스크에 일부만 기록된 데이터 페이지 등에 대한 일련의 복구 작업이 자동으로 진행된다.

 

InnoDB는 기본적으로 MySQL 서버가 시작될 때 자동 복구를 수행하며, 하드웨어 문제로 인해 자동 복구가 불가능할 경우 innodb_force_recovery 시스템 변수를 설정해서 MySQL 서버를 시작해야 한다. 

해당 값이 커질수록 심각한 상황이기 때문에 데이터 손실 가능성이 커지고 복구 가능성은 적어진다.

 

  • 1(SRV_FORCE_IGNORE_CORRUPT)
    : 테이블스페이스 데이터나 인덱스 페이지에서 손상된 부분이 있더라도 무시하고 MySQL 서버를 시작한다.

 

  • 2(SRV_FORCE_NO_BACKGROUND)
    : InnoDB는 트랜잭션의 롤백을 위해 언두 데이터를 관리하며, 이 데이터는 메인 스레드에 의해 주기적으로 삭제(Undo purge)된다. 이 메인 스레드가 언두 데이터를 삭제하는 과정에서 장애가 발생한다면 메인 스레드를 시작하지 않기 위해 이 옵션을 사용한다.

 

  • 3(SRV_FORCE_NO_TRX_UNDO)
    : 일반적으로 MySQL 서버는 재시작 시 언두 영역의 데이터를 먼저 데이터 파일에 적용하고 리두 로그의 내용을 덮어씌워 장애 시점의 데이터를 만들어 낸다. 3으로 설정 시 장애 시점에서 최종적으로 커밋되지 않은 트랜잭션을 롤백하지 않는다.

 

  • 4(SRV_FORCE_NO_IBUF_MERGE)
    : MySQL은 INSERT, UPDATE, DELETE 등의 데이터 변경으로 인한 인덱스 변경 작업을 "체인지 버퍼"라는 곳에 저장한다.(기존에는 INSERT에서만 버퍼링이 가능했기 때문에 인서트 버퍼였으나, UPDATE, DELETE에 대해서도 버퍼링이 가능해져 이름 변경)
    이 체인지 버퍼는 데이터 파일에 병합(Merge)되어야 하며, MySQL을 종료해도 병합되지 않을 수 있다. 이 버퍼의 손상이 감지되면 에러가 발생하며, 4로 설정하면 체인지 버퍼의 내용을 무시하고 시작한다.

 

  • 5(SRV_FORCE_NO_UNDO_LOG_SCAN)
    : 언두로그를 무시하고 MySQL 서버를 시작한다.

 

  • 6(SRV_FORCE_NO_LOG_REDO)
    : 리두로그를 무시하고 MySQL 서버를 시작한다. 즉 마지막 체크포인트 시점의 데이터만 남게 된다.

 

 

 

다음 내용으로 이어진다.

 

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

5. 언두 로그(Undo Log) InnoDB는 트랜잭션과 격리 수준을 보장하기 위해 DML로 변경되기 이전 버전의 데이터를 별도로 백업한다. 이렇게 백업된 데이터를 언두 로그라고 하며 이를 아래와 같은 방식

new-age-jh.tistory.com

 

'Database' 카테고리의 다른 글

InnoDB 스토리지 엔진 아키텍처 2  (0) 2022.05.17
InnoDB 버퍼 풀과 주변 기능  (0) 2022.05.17
스레드 캐시, Connection Pool, Thread Pool  (0) 2022.05.10
MySQL 아키텍처  (0) 2022.05.06
MySQL 설정 파일  (0) 2022.05.05
Comments