![[Database] InnoDB의 MVCC와 트랜잭션 처리](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdjIyxD%2FbtsKbCl1dyD%2Fcs1sOzTEkPDi6KBJyj9G1K%2Fimg.png)
InnoDB 버퍼 풀(Buffer Pool) : 메모리 내의 캐시 영역으로, 실제 데이터를 디스크에서 읽어오지 않고 메모리에서 바로 접근할 수 있도록 하는 공간이다.
데이터 파일(Data File) : 디스크에 저장된 실제 데이터 파일이다. 모든 변경 사항은 결국 디스크에 반영되어야 한다.
1. INSERT 발생
INSERT INTO User(m_id, m_name, m_area)
VALUES(1, '이희망', '부산');
데이터가 새로 삽입되면, InnoDB 버퍼 풀에 해당 데이터가 먼저 기록된다. 버퍼 풀에 저장된 데이터는 백그라운드 프로세스에 의해 나중에 데이터 파일에 기록된다.
2. UPDATE 발생
UPDATE SET m_area = '서울'
WHERE m_id = 1;
UPDATE 작업이 발생하면서 InnoDB 버퍼 풀에서 m_id = 1인 레코드의 m_area가 부산으로 변경된다. 이때, 변경하기 이전의 데이터는 Undo 로그에 기록된다. 이는 트랜잭션 롤백에 대응하기 위한 과정이다. 따라서 InnoDB 버퍼 풀에는 m_area가 변경된 서울이 저장되어 있으나, Undo 로그에는 변경 이전의 데이터인 부산이 저장된다.
데이터 파일의 경우 이전의 데이터(부산)를 가지고 있거나, 새로운 데이터(서울)로 갱신되었을 수도 있다. 이는 디스크 파일이 체크포인트나 InnoDB 쓰기 스레드에 의해 갱신되었는지에 따라 달라진다. 두 작업이 실행되지 않았다면, 데이터 파일에는 여전히 이전 값이 남아 있을 수 있다.
- 체크포인트 : InnoDB는 주기적으로 체크포인트 작업을 하여 메모리의 변경 사항을 디스크에 반영한다. 이 과정에서 버퍼 풀에 저장된 최신 데이터가 디스크에 기록된다.
- InnoDB 쓰기 스레드 : InnoDB는 변경된 데이터를 비동기적으로 디스크에 기록한다. 버퍼 풀에 있는 데이터는 즉시 디스크에 기록되지 않고, 백그라운드 쓰기 작업에 의해 디스크에 저장된다.
버퍼 풀에 저장된 최신 데이터를 디스크로 실시간 반영을 하지 않는 이유는 I/O의 과부하를 줄이고 성능을 최적화하기 위해서이다.
3. SELECT 발생
SELECT m_area FROM User WHERE m.id = 1;
MySQL의 격리 수준에 따라 조회 결과가 달라진다.
- READ_UNCOMMITTED : 이 격리 수준은 커밋되지 않은 데이터를 읽을 수 있기 때문에, 버퍼 풀에 있는 최신 데이터인 “서울”을 조회한다.
- READ_COMMITTED : 커밋된 데이터만 읽을 수 있으므로, 커밋되지 않은 “서울”이 아닌 Undo 로그에 기록된 “부산”을 조회한다.
이렇게 하나의 레코드에 여러 버전의 데이터가 관리되는 방식을 MVCC라고 한다.
하나의 레코드에 대해서 여러 개의 버전이 Undo 로그에 기록될 수 있다. 트랜잭션이 실행되는 동안 Undo 로그를 계속 사용하게 되는데, 쌓이는 로그 데이터가 많아질수록 MySQL 서버가 느려지거나 오류가 발생할 수 있다. 따라서 트랜잭션을 길게 사용하지 않고 빠르게 완료해야 한다.
4. MVCC (다중 버전 제어)
MVCC(다중 버전 제어)는 트랜잭션의 동시성과 일관성 보장을 위해 하나의 레코드에 여러 개의 버전을 사용하는 방식이다. 트랜잭션이 실행되는 동안 다른 트랜잭션에서 데이터를 수정하더라도, 각 트랜잭션은 자신이 시작된 시점의 데이터 버전을 읽을 수 있다. 덕분에 트랜잭션 간의 충돌을 방지하고 데이터의 일관성을 유지한다.
MVCC는 Lock을 사용하지 않고 일관된 데이터 읽기를 제공한다. 이는 Undo 로그를 활용하여 이전 버전의 데이터를 저장해 두고, 필요한 경우 이를 제공함으로써 일관된 읽기를 지원한다. 트랜잭션이 변경한 데이터는 버퍼 풀에 저장되고, 이전 데이터는 Undo 로그에 저장하여 이전 버전의 데이터를 읽을 수 있게 한다.
이러한 방식으로 InnoDB는 성능과 동시성을 높이면서도 데이터의 일관성을 유지한다.