비관적 락(pessimistic lock)

비관적 락이란 트랜잭션의 시작에 S Lock, X Lock 을 걸고 시작하는 방법 입니다. DB 에 write 를 하기 위해서는 X Lock 을 받아야 하는데 이미 S Lock 이 다른 트랜잭션에 걸려 있어 write 를 위한 Lock 을 얻지 못하므로 앞선 트랜잭션이 종료되기 전까지 수정할 수 없습니다.

fig1. 비관적락의 예

낙관적 락(optimistic lock)

낙관적 락은 DB 자체에서 제공되는 락이 아닌 Application Level 에서 주어지는 Lock 입니다. 같은 조건의 경우로 두 건의 트랜잭션이 발생한다고 가정 했을 때, 하나의 트랜잭션이 먼저 commit 까지 마치고 트랜잭션을 종료하게 되면 이후에 같은 조건으로 발생된 트랜잭션은 변경된 값에 의해 동일한 조건으로는 값 수정을 할 수 없게 됩니다.

fig2. 낙관적락의 예

롤백

업데이트 하는 테이블이 2개의 테이블로 구성되었고, 2번째 테이블 업데이트시 충돌이 발생하여 롤백이 발생한다면 비관적락과 낙관적 락은 다른 처리를 하게 됩니다.

비관적 락의 경우 하나의 트랜잭션으로 묶여있기 때문에 수정이 하나 실패하면 database 단에서 해당 트랜잭션 전체에 자동으로 Rollback이 일어나게됩니다.

![fig3. 비관적락과 롤백]](/files/posts/202111/fig3.png)

낙관적 락은 Transaction 을 잡지 않기 때문에 만약 충돌이 발생하여 수정을 못한 부분에 대해서는 Application 단에서 롤백에 대한 책임을 지며 Application에서 수동으로 롤백 해줘야 합니다.

fig4. 낙관적락과 롤백

Optimistic VS Pessimistic

  • 충돌이 자주 발생하는 상황인가?
  • 읽기와 수정중 어느곳에 중점을 두고 있는가?
  • 웹 어플리케이션은 Optimistic Lock 을 주로 사용한다.

낙관적락은 성능상 유리하지만 충돌 발생시 롤백을 개발자가 직접 처리해야 하기 때문에 트랜잭션 롤백이 발생하는 비관적락 에 비해서 불리합니다. 따라서 충돌이 많이 발생되지 않고 이를 해결하기 위한 비용이 많지 않은 곳에 사용하는 것이 유리 합니다.

JPA(hibernate)를 사용한 경우 충돌이 발생한 이와같은 상황에서 Optimistic Lock Exception을 던져주기 때문에 어플리케이션 단에서 충돌이 발생 했음을 인지 가능하며 예외 처리가 가능 합니다. (entity 생성시 column 으로 사용될 값에 @version 을 사용하여 동작 가능)

Exclusive Lock (X Lock)

  • X Lock 은 write 에 대한 Lock
  • SELECT … FOR UPDATE, UPDATE, DELETE 등 수정 쿼리 수행시 각 ROW 에 걸리는 LOCK
  • X Lock 이 걸려있으면 다른 트랜잭션은 S Lock, X Lock 둘 다 걸 수 없다. (read 도 불가능)

Shared Lock (S Lock)

  • S Lock 은 read 에 대한 Lock
  • DB에 쿼리할 때 lock in share mode; 를 뒤에 명시 하면 S Lock 을 걸 수 있다.(8.0 기준, FOR SHARE 도 가능)
  • S Lock 이 걸려 있을때 X Lock 은 걸 수 없다. 즉 write 가 발생할 수 없다.

innodb 에서 Lock 을 확인하는 방법

select * from information_schema.INNODB_LOCKS;

Ref.

https://sabarada.tistory.com/175

https://jinhanchoi1.medium.com/비관적-lock-낙관적-lock-이해하기-1986a399a54

https://www.youtube.com/watch?v=onBpJRDSZGA

ryan's profile image

ryan

2021-11-25 10:00

ryan 님이 작성하신 글 더 보기