Spring DB : 조회 시, DB Lock 설정하기

    이 글은 인프런 김영한님의 강의를 복습하며 작성한 글입니다. 

    DB 조회에는 락이 필요없다.

    기본적으로 SELECT 쿼리를 이용해 DB에서 데이터를 조회하는 시점에서, 세션은 DB Lock을 얻을 수 없는 상황에서도 데이터를 조회할 수 있다. 왜냐하면 데이터 조회 시에는 락이 필요없기 때문이다. 반면에 데이터를 수정할 때는 반드시 DB 락이 있는 상황에서만 가능하다. 

     

    DB 조회 시 락 설정하기

    데이터를 조회하는 순간에 락을 획득해야 할 때가 있다. 획득하는 순간부터 트랜잭션이 끝날 때까지 이 데이터는 다른 곳에서 건드리지 않아야할 경우, DB 조회 시 락을 설정해볼 수 있다. 왜냐하면 DB 조회 시 락을 획득하면, 데이터를 수정하는 다른 DB 세션이 락을 얻지 못하는 상황이기 때문이다. 

    SELECT * FROM MEMBER WHERE MEMBER_ID = 'memberA' FOR UPDATE

    데이터를 조회함과 동시에 락을 얻고 싶은 경우, SELECT FOR UPDATE 구문을 사용하면 된다. 이 SELECT 절을 사용해서 데이터를 조회하면 조회된 데이터들에 대한 모든 DB 락을 해당 DB 세션이 가지게 된다. 그리고 DB 세션은 트랜잭션을 커밋 / 롤백하는 순간 DB 락을 반환한다. 

     

    조회시점에 락이 필요한 경우는 언제일까?

    트랜잭션이 종료되는 시점까지 해당 데이터를 다른 곳에서 변경하지 못하도록 강제로 막아야 할 때 사용한다.  예를 들어 어플리케이션 로직에서 memberA의 금액을 조회한 다음에 어플리케이션에서 아주 복잡한 로직을 처리한다. 그런데 이 계산이 돈과 관련된 매우 중요한 계산이어서 계산을 완료할 때 까지 memberA의 금액을 다른 곳에서 변경하면 안된다. 이런 상황일 때, 조회시점에 락을 얻어서 트랜잭션을 처리해주면 된다. 예를 들면 마감 정산 같은 것이 있겠다. 

     

    SELECT FOR UPDATE

    SELECT * FROM FROM MEMBER WHERE MEMBER_ID = 'memberA' FOR UPDATE
    • SELECT FOR UPDATE 구문은 기본적으로 SELECT를 하고, 가장 마지막 부분에 FOR UPDATE를 붙여주면 된다. 
    • SELECT FOR UPDATE는 락을 획득한다. 따라서 락을 획득하지 못하는 상황이면, 락을 얻을 때까지 대기한다.

     

    실습

    // 세션1
    set autocommit false;
    select * from member where member_id = 'memberA' for update
    
    // 세션2
    select * from member where member_id = 'memberA'
    
    // 세션2
    update member set money = 5000 where member_id = 'memberA'

    다음과 같이 세션1 / 세션2가 나눠서 쿼리를 처리할 것이다. 세션1은 FOR UPDATE 구문을 이용해서 조회하는 시점에 락을 획득할 것이다. 그리고 세션2는 차례대로 조회를 먼저 시도해보고, 그 다음 업데이트를 시도해볼 것이다.

     

    세션1은 SELECT FOR UPDATE 구문을 통해서 memberA를 조회했고, memberA에 대한 DB Lock을 획득했다. 이 때, 세션2 역시 SELECT 구문으로 memberA를 조회해봤다. 이 때 세션 2는 memberA가 조회가 된다. 왜냐하면 비록 memberA의 DB Lock은 세션1이 가지고 있지만, 조회에는 DB Lock이 필요하지 않기 때문에 세션2는 정상적으로 조회를 할 수 있게 되었다. 

    이 때, 세션2에 다음과 같이 Update 문을 보내본다. 그러면 아래에 쿼리 실행 내용이 나오지 않는다. 즉, Update 쿼리를 실행하기 위해 대기를 하고 있는 상태다. Update 쿼리를 하기 위해서는 DB Lock이 필요한데, 해당 데이터의 DB Lock은 아직 세션1이 가지고 있는 상황이기 때문이다. 기다리다보면 다음과 같이 Time Out이 발생한다.

    댓글

    Designed by JB FACTORY