트랜잭션의 격리 수준(isolation level)은 여러 트랜잭션이 동시에 실행될 때, 특정 트랜잭션이 다른 트랜잭션의 변경사항이나 데이터를 조회할 수 있는지를 결정하는 중요한 설정입니다. MySQL은 총 4가지 격리 수준을 제공합니다.
- READ UNCOMMITTED
- READ COMMITTED
- REPEATABLE READ
- SERIALIZABLE
이 중에서 READ UNCOMMITTED는 커밋되지 않은 데이터를 읽는 Dirty Read 문제를 일으킬 수 있고, SERIALIZABLE은 동시 처리 성능이 낮아지는 단점 때문에 거의 사용되지 않습니다.
따라서 이번 포스팅에서는 가장 자주 사용되는 READ COMMITTED와 REPEATABLE READ를 중심으로, 두 격리 수준의 차이점과 특징을 살펴보겠습니다.
READ COMMITTED
READ COMMITTED 격리 수준에서는 커밋된 데이터만 읽을 수 있습니다. 이 덕분에 Dirty Read 문제가 발생하지 않으며, 데이터의 일관성을 어느 정도 보장할 수 있습니다.
READ COMMITTED 격리 수준부터는 Undo Log를 활용하여 데이터 변경 전의 상태를 저장합니다. 이를 통해, "커밋된 데이터만 읽는다"는 READ COMMITTED의 규칙을 준수하면서도 다른 트랜잭션에서 변경 중인 데이터에 접근할 수 있습니다.
Undo Log는 데이터가 변경되기 전의 상태를 저장해두어, 트랜잭션이 커밋되기 전에도 안정적인 조회를 가능하게 합니다. 이를 통해 데이터의 가용성을 높이면서도 격리 수준을 유지할 수 있습니다.
그러나, "커밋된 데이터만 읽는다"는 READ COMMITTED의 규칙은 “하나의 트랜잭션에 같은 조회 쿼리를 여러번 수행하더라도 결과가 같아야 한다”는 NON-REPEATABLE READ 문제가 발생합니다.
위 그림처럼 update를 한 이후에 바로 commit되었다고 할 때 다른 트랜잭션이 한 번의 트랜잭션에서 같은 select 쿼리를 2번 실행하였을 때 결과가 달라지게 됩니다.
REPEATABLE READ
Repeatable Read도 Read Commited와 마찬가지로 commit된 데이터만 읽습니다. 그렇다면, Repeatable Read는 어떻게 NON-REPEATABLE READ 문제를 해결할까요?
REPEATABLE READ는 아래와 같은 방식으로 NON-REPEATABLE READ 문제를 해결합니다.
- 트랜잭션 순서 부여
모든 트랜잭션에는 고유한 순서 번호가 부여되며, 이 순서는 트랜잭션이 생성될 때마다 계속 증가합니다. - 순서 기반 데이터 접근 제한
특정 트랜잭션은 자신의 순서 번호 이하인 트랜잭션에서 변경한 것만 접근할 수 있다.
이렇게 되면,10번 트랜잭션은 트랜잭션 번호가 같거나 낮은 트랜잭션에서 변경된 레코드에만 접근할 수 있기 때문에 트랜잭션 12에서 id = 500000인 레코드를 수정한 결과가 반영된 레코드에는 접근할 수 없다.
즉, NON-REPEATABLE READ 문제를 방지합니다.
READ COMMITTED와 REPEATABLE READ 둘 다 MVCC를 이용해 commit 되기 전 데이터를 보여주는 것은 동일하지만, REPEATABLE READ에서는 언두 영역에 백업된 레코드의 여러 버전 중 몇 번째 이전 버전까지 조회할 수 있냐가 다릅니다.
'스터디 > MySQL' 카테고리의 다른 글
InnoDB스토리지 엔진 수준의 락 (0) | 2025.01.06 |
---|---|
MVCC(Multi Version Concurrency Control) (0) | 2024.11.27 |
인덱스에 대해서 알아보자 (0) | 2023.09.07 |
MySQL이 인덱스를 이용하는 방법 (0) | 2023.09.07 |
프라이머리 키를 설정할 때 주의할 점 (0) | 2023.09.05 |