들어가기 전에 앞서, 이 책은 Real My SQL 1판을 읽고 정리한 내용입니다.
틀린 내용이 있댜면 댓글로 남겨주시면 감사하겠습니다.
InnoDB 엔진은 우리가 주로 사용하는 데이터베이스 엔진 중 하나이다.
InnoDB 는 도대체 어떤 특성을 가지고 있을까? 그 특성에 대해서 간단히 공부해보도록 하자
첫번째 특성, InnoDB 는 프라이머리로 기본적으로 기본키로 클러스터링을 구성한다.
즉 프라이머리 키 값의 순서대로 FileSystem 에 저장된다는 뜻이다. 따라서 Primary Key 값을 통한 범위 탐색을 하게 되면 빠르게 검색할 수 있는 이유이다.
두번째 특성, InnoDB 는 잠금이 필요없는 일관된 읽기를 제공한다.
InnoDB 스토리지 엔진은 MVCC 를 이용해서 락을 걸지 않고 읽기 작업을 수행한다. 단 SERIALIZABLE 격리 수준은 제외이다.
세번째 특성, 자동 데드락 감지
InnoDB 는 데드락이 발생하면 바로 감지하는데, 그때 ROLLBACK 하기 가장좋은 트랜잭션을 종료해버린다. 그래서 슬로우 쿼리로그로 별로 남지 않는다. 회사에서 데드락 쿼리를 수정할때 show engine.. 뭐시기를 쳐서 확인했던거 같은데, innoDB 에서 확인하려면 거기서 볼 수 있다고 공부했던것 같다. 거기에 어떤 트랜잭션을 롤백시키고, 왜 일어났는지에 대한 이유가 적혀있었다.
InnoDB Buffer Pool
InnoDB 에는 Buffer Pool 이 존재하는데 이는 데이터 파일이나 인덱스 정보를 메모리에 캐싱하는데 이용되거나, 쓰기 작업을 버퍼에 넣어놓고 지연시켜주는 기능도 제공한다. 쓰기 작업을 버퍼에 넣고 지연하는 이유는 인덱스에서도 공부했듯이 최대한 RANDOM I/O 를 줄이기 위해서 이다. 그리고 여타 다른 백그라운드 작업들도 진행한다고 한다.
이만큼 중요한 역할을 하고 있기에, 전체 메모리의 80%를 허용해라. 라고 하는 사람도 있다고 한다. 보통 다른데 50~80% 정도로 둔다고 한다. 요런 부분들은 실제 DB 를 운영하거나 공부해야지 얻을 수 있는 지식들 같다.
Undo Log
Undo 영역은 UPDATE 나 DELETE 등으로 데이터가 변경되야 할때, 변경되기 전의 데이터를 보관하는 곳이다.
예를 들어 아래와 같은 쿼리를 입력했다고 해보자.
UPDATE member SET name='roach' WHERE id = 1;
위의 쿼리를 실행하게 되면 커밋되지 않아도 일단 현재 트랜잭션내에서 name 은 roach 일것이고, 이전에 이름인 roa 는 언두 영역에 저장될 것이다. 이 상태에서 커밋에 성공하게 되면 현재 상태를 유지시킬 것이고, 롤백을 하게 되면 언두영역의 데이터를 불러와 다시 롤백 과정을 수행하게 된다. 이를 이용해 UNDO 영역을 트랜잭션 격리 수준에 따라서 UNDO 로그를 읽게 하거나, 때론 못읽게 할 수도 있다. 그 과정에서도 UNDO 로그를 이용한다.
Redo Log
우리가 작성한 쿼리문장으로 데이터를 변경하고 커밋할때 데이터베이스는 ACID 를 보장해주기 위해서 변경된 내용들을 즉시 반영해야 합니다. 근데 이런 작업들을 하나하나씩 하게 되면 계속 말했듯이 너무나도 많은 랜덤 디스크 쓰기 작업이 일어나게 됩니다. 그래서 이러한 부하를 피하기 위해서 위에서 말했듯이 InnoDB 에서는 Buffer Pool 을 이용합니다. 하지만 이런 것으로는 완전하게 ACID 를 보장할 수 없어, 변경해야 하는 내용들은 로그로 남겨두고 한번에 쌓아서 처리할 수 있는데, 그 로그를 Redo Log 라고 합니다.
MVCC(Multi Version Concurrency Control)
InnoDB 에서는 잠금을 사용하지 않고 일관된 읽기를 제공하는 것이 중요한데, InnoDB 는 이를 Undo Log 를 통해 구현한다고 합니다.
예를 들면, 아래와 같은 그림을 한번 봅시다.
기존 유저테이블의 데이터가 위와 같다고 생각해봅시다. 여기서 우리는 name 을 "roach" 로 변경시키는 쿼리를 작성한다고 했을때 어떤일이 일어날까요?
UPDATE member SET name='roach' WHERE id = 1;
위에서 배운 내용대로 라면 아래와 같은 상황이 될것입니다.
Disc 를 roa 혹은 roach 로 해둔이유는 아까도 말했듯이, 버퍼에 쌓아놓고 한번에 하므로 언제 업데이트 될지 모릅니다. 그래서 저렇게 표기해두었습니다. 일단 여기서 어떻게 언두로그를 이용해서 트랜잭션 격리수준에 따른 결과를 보여주나 하면, 만약READ_UNCOMMITED 일 경우에는 COMMIT 되지 않은 값을 읽어오므로, InnoDB 버퍼 풀이나 데이터 파일에서 부터 온 결과를 읽으면 됩니다.
혹은 READ_COMMITED, SERIALIZABLE, REPEATABLE_READ 의 경우에는 커밋된 값만을 읽어와야 하므로, Undo Log 에 있는 값을 읽어오면 될것입니다. 이러한 프로세스를 DB 에서는 MVCC 라고 합니다.
그래서 이를 이용해서 잠금 없이 읽기가 가능합니다. 예를 들면 유저 A 는 1번에 값을 변경시키는 트랜잭션이 진행중인데, 유저 B 는 1번을 볼때 격리 수준에 의해 Undo Log 나 Buffer Pool 을 보게 될것이므로 잠금 없이 일관된 읽기를 제공해줄 수 있습니다.
여기까지 간단하게 InnoDB 에 대해서 정리해보았습니다..
아직까지 초보개발자다 보니 틀린내용이 있을 수 있으니 댓글로 남겨주시면 감사하겠습니다.
'데이터베이스 > MySQL' 카테고리의 다른 글
인덱스 스캔 방식 (0) | 2021.11.08 |
---|---|
MySQL Index (0) | 2021.10.31 |
MySQL Lock System (0) | 2021.10.25 |
MySQL 에 쿼리가 들어왔을때? (0) | 2021.10.21 |
회사코드 DeadLock 처리 정리 (0) | 2021.09.20 |