공유 락/배타 락과 데드락

2024. 2. 9. 11:35CS/Database

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

  • 공유 락(읽기 락)
    • 공유 락이 걸린 데이터는 다른 트랜잭션에서 읽기만 가능하고 쓰기는 불가능하다.
    • 즉, 공유 락이 걸린 데이터에 대해서 다른 트랜잭션도 똑같이 공유 락을 획득할 수 있다. 단, 배타 락은 획득할 수 없다. 
    • 따라서 공유 락을 사용하여 조회한 데이터는 트랜잭션 내내 변경되지 않음이 보장된다.
  • 배타 락(쓰기 락)
    • 배타 락이 걸린 데이터는 다른 트랜잭션에서 읽기와 쓰기 모두 불가능하다.
    • 즉, 배타 락이 걸린 데이터에 대해서 다른 트랜잭션은 공유 락, 배타 락 둘 다 획득할 수 없다.
    • 즉, 배타 락을 획득한 트랜잭션은 해당 데이터에 대한 독점권을 갖는 것이다.

정리해보면 아래 표와 같이 배타 락이 개입하는 경우 양립이 불가능해진다. 

  공유 락 배타 락
공유 락 허용 대기
배타 락 대기 대기
  • 공유 락이 걸린 데이터에 대해 공유 락을 획득하는 것은 허용된다.
  • 공유 락이 걸린 데이터에 대해 배타 락을 획득하려면 대기해야 한다.
  • 배타 락이 걸린 데이터에 대해 공유 락을 획득하려면 대기해야 한다.
  • 배타 락이 걸린 데이터에 대해 배타 락을 획득하려면 대기해야 한다.

이러한 특성으로 인해 데드락이 발생할 수 있다.

MySQL에서의 공유 락과 배타 락

공유 락을 획득하려면 SELECT FOR SHARE를 사용하면 되고, 배타 락을 획득하려면 SELECT FOR UPDATE를 사용하면 된다.

SELECT * FROM user WHERE user_id = 1 FOR SHARE; // 공유 락 획득
SELECT * FROM user WHERE user_id = 1 FOR UPDATE; // 배타 락 획득

데드락

데드락은 서로가 점유하고 있는 자원에 대해 무한정 대기하고 있는 상황을 의미한다. 

 

데드락은 트랜잭션 격리 수준이 SERIALIZABLE인 경우 자주 발생할 수 있다.

  • 예를 들어 트랜잭션 1이 데이터 1을 조회하며 읽기 락을 획득했고, 트랜잭션 2도 동시에 데이터 1을 조회하며 읽기 락을 획득했다고 가정하자.
  • 트랜잭션 1이 데이터 1을 수정하기 위해 배타 락을 획득해야 하는데, 트랜잭션 2가 읽기 락을 갖고 있어서 대기한다.
  • 마찬가지로 트랜잭션 2도 데이터 1을 수정하기 위해 배타 락을 획득해야 하는데, 트랜잭션 1이 읽기 락을 갖고 있어서 대기한다.
  • 즉 트랜잭션 1과 트랜잭션 2는 서로의 읽기 락이 해제될 때까지 무한정 대기한다. 이를 데드락이라 한다.

Reference