공유 자원에 여러 트랜잭션이 접근하게 된다면 어떠한 상황이 발생할게 될까?
예를 들어 A 트랜잭션이 커밋하기 전 B 트랜잭션에서 같은 자원에 접근하여 데이터의 변경 작업이 발생한다면 데이터의 정합성이 깨지게 될 것이다.
이러한 상황의 해결책은 바로 Lock이다.
단어 뜻 그대로 데이터의 변경을 일으키기 전에 잠금을 설정하고 트랜잭션을 수행하는 것이다.
한 트랜잭션을 시작하고 데이터를 수정하는 동안에는 커밋이나 롤백 전까지 다른 트랜잭션에서 해당 데이터를 수정할 수 없게 막는 역할을 수행한다.
락을 획득하지 못한 트랜잭션은 락을 획득하기 전까지 기다린다.
트랜잭션을 커밋한 후, 락을 반납하도록 구현해야 한다. (락이 먼저 반납된다면 다른 트랜잭션에서 커밋되지 않은 동일한 데이터에 접근하여 변경 작업이 일어나 데이터의 정합성이 깨질 수 있다.)
Lock의 종류에는 공유 락, 베타 락이 존재한다.
공유 락 (Shared Lock)은 읽기 락(Read Lock)이라고 불리며, 공유 락이 걸린 데이터에 대해서는 읽기 연산만 가능하다.
공유 락이 걸린 데이터에 대해서 다른 트랜잭션도 동일하게 공유 락을 획득하여 해당 데이터에 대해 읽기 연산을 수행할 수 있다.
공유 락은 공유 자원에 대해 락을 획득한 트랜잭션 이외의 다른 트랜잭션에 의해서는 데이터가 변경되지 않음을 보장한다.
다른 트랜잭션에 대해 읽기 연산 O, 쓰기 연산 X
SELECT FOR SHARE를 통해 특정 데이터로 부터 공유 락을 획득할 수 있다.
SELECT * FROM TABLE WHERE ID = 1 FOR SHARE
베타 락 (Exclusive Lock)은 쓰기 락 (Write Lock)이라고 불리며, 베타 락을 획득한 트랜잭션은 읽기 및 쓰기 연산이 가능하다.
하지만, 락을 획득하지 못한 트랜잭션은 베타 락이 걸린 데이터에 대해 읽기 및 쓰기 연산이 불가하다. (이를 블로킹 상태 라고 한다.)
다른 트랜잭션에 대해 읽기 연산 X, 쓰기 연산 X
SELECT FOR UPDATE를 통해 특정 데이터로부터 베타 락을 획득할 수 있다.
SELECT * FROM TABLE WHERE ID = 1 FOR UPDATE
락 사용은 데이터의 정합성을 보장할 수 있다는 점에서 용이하지만 락 획득 후 트랜잭션이 순차적으로 수행되는 플로우이기에 성능 저하가 발생할 수도 있다. 다음 포스팅을 통해 락을 사용할 경우 발생할 수 있는 문제점들과 이를 해결하는 방안에 대해 알아보며 락에 대해 더 자세히 알아보도록 하겠다.