이 글에서 사용한 dbms는 MySQL 8.x 버전이고 innoDB engine 기준입니다.
아~주 기본적인 레벨, 거의 시작점 수준의 이야기이니 감안해주세요.
저는 Real MySQL을 통해 DB를 공부하던 중 S-Lock
과 X-Lock
에 대해 알게 되었습니다.
그리고 SELECT - FOR UPDATE
쿼리는 해당 레코드의 X-lock을 획득한다는 사실도 알게되었고,
이 사실을 이용해 직접 실습을 해보던 중 저의 뇌가 꼬이기 시작했습니다.
S-Lock은 Shared-Lock, 읽기 락과 동일한 의미이고
X-Lock은 Exclusive-Lock, 쓰기 락, 배타적 락과 동일한 의미입니다.편의상 섞어쓸 수 있고, 이 이름들 또한 제가 헷갈렸던 부분이라 미리 정리했습니다.
1번 트랜잭션이 A레코드의 쓰기락을 얻었음에도 2번 트랜잭션은 아무 일 없이 A레코드를 조회하는데 성공했습니다. 왜일까요?
제가 SELECT와 S락에 대한 오해를 하고 있었기 때문입니다.
너무 당연한 말같지만... 저는 SELECT가 곧 S락이라고 무의식중에 생각하고 있었습니다.
그 배경은 S락과 X락의 차이를, 그리고 그 자체를 이해하지 못했기 때문입니다.
그래서 우선 위의 읽기는 행위일 뿐, 락이 아니다. 를 강조하고 싶고, 이어서 S락과 X락을 설명해보겠습니다.
개념을 외우기만 했다면 쓰기락에 대해 쓰기락을 걸면 다른 트랜잭션이 읽지 못한다.
라고 말할 수도 있습니다. (제가 그랬습니다. ㅎㅎ) 하지만 이것은 틀린 표현이라 생각합니다.
위의 문장을 고쳐보겠습니다.
아니, 그래서 S락은 뭐고 X락은 뭔가!
S락과 X락은 비슷합니다.
둘 다 레코드에 잠금을 걸고, 잠금이 걸린동안 다른 트랜잭션이 수정하지 못하도록 막는 일을 합니다.
내가 작업하는 동안 레코드의 내용이 계속 바뀌면 이 레코드를 신뢰할 수 없으니까 내 작업이 마치기 전까지는 아무도 건들지 마! 하고 잠금을 거는겁니다.
책의 내용에 대한 기억을 더듬어보며 정의해보자면
별 차이없어 보이지만, 제가 생각하는 이 둘의 결정적인 차이는 락 사이의 호환여부입니다.
이게 무슨 말이냐면, 1번 트랜잭션이 어떤 레코드 A에 대해 S락을 얻었다고 가정합시다.
여기까지가 간략은 S락과 X락에 대한 설명이었고, 그렇다면 다시 본론으로 넘어가겠습니다.
X락과 S락은 호환되지 않기때문에 X락이 걸려있으면 S락 시도도 대기상태에 빠진다했는데, 왜 SELECT는 되는걸까요?
사실상 이 둘이 이 글에서 말하는 전부입니다.
X락을 그 레코드에 걸었든, 말든, MySQL InnoDB엔진은 SELECT시 S락을 걸지 않으니 조회가 가능한 것입니다.
물론 어떤 DBMS에서는 SELECT시에 S락을 획득한다고 합니다.
이러한 특징을 가진 DBMS에서는 X락이 걸린 레코드에 SELECT를 시도하면 대기가 발생할 것입니다.
(S락과 X락의 호환여부가 무엇을 의미하는지 이해하고, SELECT는 S락이 아님 을 이해하면 다른 DBMS에서 SELECT시 대기가 발생해도 이해할 수 있을거라 믿습니다.)
만약 MySQL InnoDB 엔진에서도 위의 상황처럼 X락이 걸린 레코드에 SELECT시 대기하는 상황을 보고싶다면,
글을 마무리하기 전에 다시한번 강조하고 마치겠습니다.
별거 아닌 주제를 길게 썼는데 저는
이 두가지가 DB를 이해하는데 많은 도움이 되었어서 정리해보았습니다.
innodb에서 select를 사용할 경우, Consistent Nonlocking Reads로 동작해서 undo 로그에 있는 snapshot을 읽는 것으로 알고 있습니다. select가 락이 걸린 것을 읽을 수 없어야 하는데 innodb는 undo 로그까지 락을 걸지 않아서 select ... for update로 락이 걸린 것을 select를 통해서 읽을 수가 있습니다.