참고
MVCC(다중 버전 동시성 제어)
NOTE
동시 접근을 허용하는 데이터베이스에서 동시성을 제어하기 위해 사용하는 방법!
InnoDB 스토리지 엔진 아키텍쳐
•
데이터베이스를 사용하는 가장 큰 이유 중 하나는 바로 트랜잭션 때문이다.
◦
하지만 모든 DBMS가 트랜잭션 기능을 제공하지 않는다.
◦
대표적으로 MySQL의 스토리지 엔진중 하나인 MyISAM
◦
MySQL의 InnoDB는 레코드 단위까지의 트랜잭션 지원
•
레코드 수준의 트랜잭션을 지원하기 위해서 InnoDB는 MVCC를 사용한다.
◦
MVCC → 동시성을 제어하기 위해 사용하는 방법 중 하나.
◦
스냅샷을 통해 하나의 레코드에 여러 버전이 관리가 된다.
◦
데이터에 대한 변경이 완료(Commit)되기 전까지의 변경 사항은 다른 사용자가 볼 수 없도록 할 수 있다.
•
MVCC를 사용하는 이유는 락을 사용하지 않기 위해서이다.
◦
락을 사용하는건 동시성 제어에서 가장 기본적인 방법이다.
◦
하지만 락은 동시성을 떨어트리므로, MVCC를 통해 보완한다.
버퍼풀(Buffer Pool)
NOTE
스토리지 엔진의 핵심 부분으로, 디스크에 저장된 테이블과 인덱스 정보(엄밀히는 페이지)를 캐시해두는 공간이다!
•
캐싱을 통한 읽기 성능 향상
◦
데이터를 임시 저장하는 메모리 공간이다
◦
읽기 작업시에 디스크 읽기 횟수를 줄여 성능을 높인다.
•
쓰기 지연을 통한 쓰기 성능 향상
◦
여러 건의 디스크 쓰기를 한 번에 처리할 수 있는 역할을 한다.
◦
쓰기 작업을 매번 따로 수행하면 데이터 처리할 위치를 찾아야하는 랜덤 I/O가 발생하지만, 버퍼풀을 사용하면 일괄처리를 해서 I/O를 줄여 성능이 올라간다.
버퍼 vs 캐시
•
버퍼
◦
데이터를 전송하는 상호간의 장치간의 속도차이로 고속의 장치가 기다리는 현상을 줄여주는 방식
◦
ex) 프린트를 인쇄한다고 할 떄, 버퍼가 없다면 컴퓨터는 모든 페이지를 인쇄하기 전까지 기다린다.
▪
버퍼를 사용하면 컴퓨터는 버퍼로 데이터를 보내고, 프린터는 컴퓨터로 데이터를 받지않고 버퍼를 통해서 받는다.
◦
데이터의 손실을 막기 위해서도 사용한다.
•
캐시
◦
속도가 다른 두 기기간의 병목 현상을 완화해주는 장치다.
◦
고속의 기기에 대해 미리 데이터를 받아두고 저속의 기기까지 거치지않고 데이터를 가져온다.
Undo Log
NOTE
MySQL이 트랜잭션과 격리 수준을 보장하기 위해 백업해둔 변경 전의 데이터!
•
트랜잭션 보장
◦
트랜잭션이 롤백되면 변경된 데이터를 백업된 이전으로 복구 시킨다.
•
격리수준 보장
◦
특정 커넥션에서 데이터를 변경하는 도중에 다른 커넥션에서 데이터를 조회하면 격리 수준에 맞는 데이터를 반환한다.
•
데이터베이스는 커밋 여부와 무관하게 실제 데이터와 버퍼풀(메모리)의 내용을 변경한다.
•
그리고 언두 영역에는 변경적의 값을 백업해두다가 커밋되면 현재 상태를 유지하고, 롤백되면 백업데이터로 복구한다.
•
이러한 방식 때문에 아래와 같은 상황은 좋지않다.
◦
대량의 트랜잭션을 변경/삭제 하는 경우(변경/삭제 마다 언두로그도 복사되므로)
◦
트랜잭션을 오래 유지하는 경우(계속해서 로그가 쌓이므로)
Redo Log
NOTE
트랜잭션 ACID중에서 D에 가장 밀접하게 연관되어 있다!
•
커밋됐지만 데이터 파일에 기록되지 않은 데이터
•
롤백됐지만 데이터 파일에 이미 기록된 데이터
•
데이터 변경 내용을 리두 로그로 기록하고, 이를 통해 MySQL 서버가 비정상적으로 종료됐을 때 일관된 데이터를 가지도록 한다.
데이터베이스가 트랜잭션을 지원하는 방법과 동작 과정
트랜잭션
NOTE
잠금이 존재하는 이유
⇒ 동시성을 제어하기 위함
트랜잭션이 존재하는 이유
⇒ 데이터의 정합성을 보장하기 위함
•
트랜잭션은 계좌 이체처럼 여러 작업들로 묶이는 하나의 논리적인 작업을 완벽하게 처리한다.
•
만약 문제가 있다면 일부 작업만 적용되는 부분 업데이트 문제를 해결해준다.
•
트랜잭션은 하나의 논리적인 작업 자체가 완전히 적용(Commit) 되거나 아무것도 적용되지 않음(Rollback)을 보장해준다.
트랜잭션의 동작 과정 예시
NOTE
격리수준 READ_COMMITED인 경우 데이터의 변경을 어떻게 처리하는지 알아보자!
INSERT INTO member(id, name, area) VALUES (1, "MangKyu", "서울");
SQL
복사
데이터를 추가
INSERT문이 실행되면 버퍼풀과 디스크에 각각 저장된다.
START TRANSACTION;
UPDATE member SET area = "경기" WHERE id = 1;
SQL
복사
UPDATE로 데이터 갱신
버퍼풀 → 데이터 갱신
Undo log → 이전 데이터
•
디스크는 백그라운드 쓰레드에 의해서 처리가 되므로 시점에 따라 생산되지 않았을 수도 있다.
•
하지만 MySQL은 ACID를 보장하므로 일반적으로는 버퍼풀과 동일하다고 보면된다.
•
MVCC를 통해 동일한 레코드가 여러 버전으로 관리되고 이를 통해 커밋 이전의 데이터 읽기, 롤백 등이 가능해졌다!
◦
그렇다면 아직 커밋 또는 롤백이 되지 않은 경우 데이터를 조회하면 어떤 데이터가 조회되는가?
◦
이는 격리 수준에 따라 다르다.
▪
READ UNCOMMITED
•
커밋 여부와 무관하게 버퍼풀의 데이터를 반환
▪
READ COMMITED, REPETABLE READ, SERIALIZABLE
•
백업된 언두 영역의 데이터를 반환한다.