[DB] 낙관적 락 VS 비관적 락

2023. 7. 10. 23:04DataBase

이커머스 프로젝트를 하다보니 동시성 문제가 여러 곳에서 일어날 수 있다는 것을 느꼈다. 처음엔 Syncronized를 붙여서 동시성을 해결한줄 알았지만 여러 서버에서 동시 요청을 했을 때 Syncronized는 동시성 문제를 해결해줄 수 없음을 깨달았다. (한 프로세스 내에서만 동기 처리를 해줌)

 

그래서 동시성 문제를 해결하기 위해서 트랜잭션의 격리성을 공부하게 되었고, 트랜잭션의 격리성을 공부하다 보니 '동시성을 어떠한 방식으로 해결할까' 에 대한 고민을 할 수 밖에 없었다.

 

가장 보편적인 방법으로 낙관적 락과 비관적 락이 있어서 두 Lock을 비교하며 정리해봐야겠다.

 

- 낙관적 락

  : 낙관적 락은 DB가 아닌 Application Level 에서 동시성을 해결한다.

@Version을 통해 버전을 관리하는 필드를 지정한 후 쓰기(write)가 있을 시 update에 version이 증가하게 된다.

그리고 이렇게 상태 변경시에 version의 정보를 확인해서 읽었을 때의 version과 다르면 예외를 발생시킴으로써 동시성을 보장한다. 

 

  : 낙관적 락의 경우는 트랜잭션을 사용하지 않는다. 그래서 당연히 성능 면에서 비관적 락보다 뛰어나다. 하지만 예외가 발생할 시에 롤백(Rollback)을 보장해주지 않기 때문에 개발자가 직접 롤백 로직을 작성해주어야 한다.

그렇기 때문에 예외가 많이 발생할 것 같은 상황에서 사용하면 많은 노력과 비용이 들 것이다.

------------예시------------
@Entity
public class Board {

  @Id
  private String id;
  private String title;

  @Version
  private Integer version;
}

 

 

- 비관적 락 

  : 비관적 락은 트랜잭션이 시작될 때 해당 테이블의 row에 shared lock을 걸어 다른 트랜잭션이 쓰기(wirte) 기능을 하지 못하도록 막는 것이다. (데이터 정합성 보장)

해당 트랜잭션을 제외한 모든 트랜잭션이 종료되었을 때 쓰기(write)가 실행된다. 즉, shared lock을 점유하고 있는 트랜잭션들이 끝나야지만 쓰기 기능으로 접근할 수가 있다. 즉, Reeatable Read 또는 Serializable 정도의 격리성 수준을 제공한다.

 

: 간단하게 사용할 수 있지만 성능 이슈가 발생할 수 있다. 만약 로직에서 여러 개의 테이블을 수정하는 작업을 한다면 트랜잭션을 길게 하나로 묶을 수 밖에 없다. 이러한 로직에 많은 트래픽이 몰리게 된다면 트랜잭션이 지연될 것이고 이는 성능 저하로 이어질 것이다.

 

무조건 뭐가 좋다고 할 수 없기 때문에 개발하고 있는 애플리케이션의 특성과 상황을 잘 고려해서 선택하여 사용해야겠다 !

 

https://sabarada.tistory.com/175

https://hudi.blog/jpa-concurrency-control-optimistic-lock-and-pessimistic-lock/

'DataBase' 카테고리의 다른 글

[DB] Transaction 격리성  (0) 2023.07.10