배타 락이 걸린 레코드를 일반 조회할 수 있다?

Woody·2024년 7월 24일

TIL

목록 보기
2/19

배경

부트 캠프 실습 코치를 진행하면서 수강생으로부터 아래와 같은 질문이 들어왔다.

=> 질문

트랜잭션에서 배타 락을 사용하여 특정 ROW를 가져오면, 해당 트랜잭션이 끝날 때까지 해당 ROW는 다른 트랜잭션에서 조회 및 수정이 불가능한 것으로 알고 있습니다. 그러나 실제로 테스트해본 결과, 트랜잭션에서 배타 락을 통해 특정 ROW를 조회한 후 아직 작업이 진행 중일 때도 다른 트랜잭션에서 해당 ROW에 대한 일반 조회가 성공하는 것을 확인했습니다. 저는 이러한 상황이 더티 리드가 발생했다고 생각하고, 왜 더티 리드 현상이 발생했는지 궁금합니다.

위 질문을 보고 2가지가 의문이 들었다.

  1. 내가 알고있는 더티 리드 문제와 다른 것 같은데, 저 현상이 더티 리드가 맞나?
  2. 배타 락을 통해 조회하면 해당 트랜잭션이 끝날 때까지 조회 및 수정이 불가능하지 않나?

이 상황이 더티 리드가 맞나?

우선 더티 리드에 관해 수강생의 잘못된 개념을 먼저 정정했다.

=> 답변

특정 트랜잭션에서 처리한 작업이 완료되지 않았는데도 다른 트랜잭션에서 수정된 데이터를 볼 수 있는 현상을 더티 리드라고 합니다.
더티 리드는 READ UNCOMMITTED 격리 수준에서만 발생할 수 있으며, 수강생의 데이터베이스인 H2 데이터베이스의 기본 격리 수준은 READ COMMITTED이기 때문에 더티 리드가 발생하지 않습니다.
따라서 위 현상에서 더티 리드가 발생했다고 보기 어려울 것 같습니다!

정말 조회가 가능할까?

이후 2번 상황을 실험해본 결과, 배타 락을 통해 조회한 ROW에 대해 다른 트랜잭션에서 일반 조회가 가능한 것을 확인했다.
이에 대한 현상이 궁금해서 구글링을 진행했고, 2개의 블로그를 통해 다음과 같은 결론을 내렸다.

블로그1블로그2

2번째 사진에서 ’배타 락이 걸려있다면 다른 트랜잭션은 공유 락, 배타 락 둘 다 획득 할 수 없다.’ 이 부분을 주목해야 한다.
즉, 배타 락이 걸려있는 ROW에 대해 다른 트랜잭션이 또 다른 배타 락을 걸지 못함을 의미한다.
따라서 첫번째 사진과 같이 배타 락이 걸려있는 ROW를 일반 SELECT 문으로 조회할 수 있는 것이다.

어떻게 배타 락을 통한 조회와 일반 조회가 동시에 가능할까?

배타 락 또는 공유 락으로 레코드에 대한 접근을 잠근다면, 해당 트랜잭션이 끝날 때까지 다른 트랜잭션들이 접근할 수 없기 때문에 동시성 처리의 효율이 떨어진다.

이를 개선하기 위해 데이터베이스는 MVCC(Multi-Version Concurrency Control)라는 방법을 사용한다. 이는 원본 데이터에 대한 스냅샷을 보관하고, 일반 데이터 조회 시 해당 스냅샷에서 데이터를 조회하여 동시성 처리 효율을 높인다.
하지만 배타 락을 통해 데이터를 조회할 때는 스냅샷이 아닌 테이블에 직접 접근하여 데이터를 조회한다.

따라서 배타 락을 통한 조회는 테이블에서 데이터를 조회하고, 일반 조회는 스냅샷에서 데이터를 조회하기 때문에 배타 락을 통한 조회와 일반 조회가 동시에 가능한 것이다.

참고

MySQL 8.0의 공유 락(Shared Lock)과 배타 락(Exclusive Lock)

공유락(Shared Lock) & 배타락(Exclusive Lock)

[MySQL] 트랜잭션의 격리 수준(Isolation Level)에 대해 쉽고 완벽하게

[Database] MVCC(다중 버전 동시성 제어)란?

0개의 댓글