데이터베이스를 사용하는 가장 큰 이유는 뭘까요?
저는 다양한 기술들이 중요하다고 생각하지만 무엇보다도 Transaction
이라는 기술은 굉장히 중요하다고 생각하고 있습니다.
여기서 Transaction을 간단하게 짚어보고 넘어가겠습니다.
트랜잭션(Transaction)은, 데이터베이스의 상태를 변화시키기 위해 수행하는 작업의 단위를 뜻합니다.
간단히 DML(SELECT, INSERT, DELETE, UPDATE)을 통하여 데이터베이스의 기록을 변경할 수 있습니다.
여기서 작업의 단위는 이런 DML 쿼리 질의어 한 문장이 아니라 여러 문장을 묶어 하나의 작업의 단위로 만들 수 있음을 알고 있어야 합니다.
모든 DBMS가 이런 트랜잭션 기능을 제공하는 것은 아닙니다. MySQL만 보아도 스토리지 엔진에 따라 다릅니다. MyISAM은 트랜잭션을 지원하지 않는 반면에 InnoDB는 레코드 단위까지 트랜잭션을 지원합니다.
이제 여기서 MVCC 내용으로 조금씩 넘어가보도록 하겠습니다.
Multi Version이란 하나의 레코드에 대해서 여러 개의 버전을 둔다는 의미입니다. 여러 버전을 두게 되면 어떤 장점이 있을까요?
바로 데이터베이스의 데이터에 대한 변경이 완료(commit)되기 전까지의 변경 사항을 다른 사용자가 볼 수 없도록 하는 등의 제어가 가능하게 됩니다.
MVCC는 스냅샷을 이용하여 구현하게 됩니다. 스냅샷을 통해 여러 버전의 관리를 가능하게 하는 것입니다.
아까 말씀드렸다시피 MVCC를 이용하지 않는 DBMS도 존재한다고 이야기했습니다.
그러면 MVCC를 이용하지 않으면 동시성 제어를 하지 못하는 것일까요? 그것은 아닙니다.
MVCC를 이용하는 이유는 락을 사용하지 않기 위함
이라고 말할 수 있습니다.
동시성 제어를 이루는 것 중에 Lock이라는 방법이 있습니다. Lock은 동시성 제어를 이루기 위한 가장 쉬운 방법일 수도 있지만 다들 아시다시피 성능 상 요청 처리 속도가 저하될 수 있는 문제를 안고 있습니다.
이런 Lock의 단점을 피하기 위해서 MySQL은 언두 로그(Undo Log)
를 활용합니다.
언두 로그란 MySQL(DB Engine : InnoDB)이 트랜잭션과 격리 수준을 보장하기 위해 백업해둔 변경 전의 데이터입니다.
이를 어디서 사용할까요?
MySQL에서 언두 로그와 마찬가지로 데이터 변경 내용을 리두 로그로 기록하고, 이를 통해 MySQL 서버가 비정상적으로 종료됐을 때 일관된 데이터를 갖도록 도와줍니다. 이는 ACID중 Durability와 밀접한 기술입니다.
서버가 비정상적으로 종료되었을 때 다음과 같은 문제가 발생할 수 있습니다.
첫번째 경우엔 리두 로그의 내용을 복사하기만 하면 된다.
롤백된 경우라면 리두 로그만으로 해결되지 않는데, 변경 전의 데이터 내용을 갖는 언두 로그의 데이터 내용을 복사하면 될 것입니다. 그래도 리두 로그가 필요한 이유는 해당 트랜잭션이 커밋됐는지 롤백됐는지 아니면 실행 상태였는지를 확인하기 위함입니다.
UPDATE membet SET m_area = "경기" WHERE m_id = 12;
해당 쿼리(질의문)를 실행했다고 하면 위 사진과 같은 변경 사항이 적용될 것입니다.
만약 COMMIT이나 ROLLBACK 되지 않은 상태에서 다른 사용자가 해당 데이터를 조회하면 어떻게 될까?
이 질문에 대한 답은 MySQL 서버의 시스템 변수(transaction_isolation)에 설정된 격리 수준(Isolation level)에 따라 다릅니다.
언두 영역의 데이터는 항상 바로 삭제되지는 않고 언두 영역을 필요로 하는 트랜잭션이 더이상 존재하지 않을 경우에 비로소 삭제됩니다.
리두 로그도 버퍼(메모리) 공간이 존재합니다. 리두 로그의 내용을 반영하려면 랜덤 I/O를 통하여 데이터 저장 위치를 찾아야 하는데 매번 디스크에 접근하지 않고 일정 주기로 버퍼의 내용을 디스크에 동기화
하도록 되어 있습니다.
[MySQL] MVCC(다중 버전 동시성 제어)와 데이터베이스가 트랜잭션을 지원하는 방법과 동작 과정