SELECT FOR UPDATE vs LOCK IN SHARE MODE

이상민·2021년 11월 3일
2
post-thumbnail

데이터베이스 동시성 문제

출처 : https://dololak.tistory.com/446

  • 위에 예시처럼 데이터베이스에서 race condition이 있으면 잔여좌석이 2 줄어들 것이 하나만 줄어드는 문제가 발생할 수 있다

  • 레코드 단위 락을 걸어 이런 문제를 방지할 수 있는데, SELECT FOR UPDATE 또는 LOCK IN SHARE MODE를 사용해볼 수 있다

  • 이 두 구문을 locking read라고 부른다


SELECT FOR UPDATE

데이터를 수정하기위해 SELECT하는 중이기 때문에 다른 트랜잭션이 레코드를 SELECT하지 못하게 read, write락을 거는 구문

SELECT 컬럼 FROM 테이블 WHERE 조건 FOR UPDATE;

출처 : https://dololak.tistory.com/446

  • SELECT의 대상이 되는 레코드들에 read, write 락을 걸어 다른 locking read가 레코드를 조회하거나 레코드를 수정할 수 없게 한다

  • 기본적으로 락을 획득할때까지 무한정 기다린다. FOR UPDATE NOWAIT(= WAIT 0)처럼 옵션을 주어 락을 바로 획득하지 못할 시 예외를 발생하도록 할 수도 있다

  • FOR UPDATE를 사용한 트랜잭션이 커밋되어야 락이 풀린다

  • 정리 : 선택한 레코드가 트랜잭션의 커밋 전 수정될 수 있으니 다른 트랜잭션이 read lock을 얻거나 수정할 수 없게 한다


LOCK IN SHARE MODE

선택된 레코드들에 shared 락, write 락을 거는 구문

  • SELECT의 대상이 되는 레코드들에 write 락을 걸어 다른 트랜잭션이 수정할 수 없게 한다. FOR UPDATE와는 다르게 읽기는 가능하다

  • FOR UPDATE와 동일하게 락을 획득할때까지 기다린다

  • LOCK IN SHARE MODE를 사용한 트랜잭션이 커밋되어야 락이 풀린다

  • SHARED LOCK이 이미 걸려 있어도 다른 트랜잭션이 LOCK IN SHARE MODE를 사용할 수 있다. 이때 두 트랜잭션이 레코드를 수정하려고 하면, 서로의 락에 의해 데드락이 발생한다. 먼저 UPDATE를 시도한 트랜잭션이 타임아웃되어서 실패하고, 다른 트랜잭션이 성공한다. 결과적으로 하나의 수정만 성공한다

  • 정리 : 선택한 레코드를 읽기만하고 수정하지 않는다. 여러 트랜잭션이 read lock을 얻을 수 있다. 해당 레코드를 수정하는 트랜잭션은 락이 풀리기를 기다려야한다


참고자료

https://dololak.tistory.com/446

https://dev.mysql.com/doc/refman/5.7/en/innodb-locking-reads.html

profile
편하게 읽기 좋은 단위의 포스트를 추구하는 개발자입니다

0개의 댓글