JPA는 데이터베이스 트랜잭션 격리 수준을 READ COMMITTED 정도로 가정한다.
만약 일부 로직에 더 높은 격리 수준이 필요하면 낙관적 락과 비관적 락 중 하나를 사용하면 된다.
낙관적 락
트랜잭션 대부분은 충돌이 발생하지 않는다고 낙관적으로 가정하는 방법이다.
이것은 데이터베이스가 제공하는 락 기능을 사용한 것이 아니라 JPA가 제공하는 버전 관리 기능을 사용한다. 쉽게 이야기해서 애플리케이션이 제공하는 락이다.
낙관적 락은 트랜잭션을 커밋하기 전까지는 트랜잭션의 충돌을 알 수 없다는 특징이 있다.
비관적 락
트랜잭션의 충돌이 발생한다고 가정하고 우선 락을 걸고 보는 방법이다.
이것은 데이터베이스가 제공하는 락 기능을 사용한다. 대표적으로 select for update 구문이 있다.
두 번의 갱신 분실 문제(Second lost updates problem)
만약 사용자A와 사용자B가 동시에 동일한 공지사항 글 수정페이지에 들어가서 사용자A가 수정완료 버튼을 눌러 수정을 하고 그 다음 사용자B가 수정완료 버튼을 클릭했다고 했을때 공지사항 글은 사용자B의 수정사항 데이터만 남게 된다.
이것을 두 번의 갱신 분실 문제(Second lost updates problem)라 한다.
두 번의 갱실 분실 문제는 데이터베이스 트랜잭션의 범위를 넘어선다. 따라서 트랜잭션 만으로는 문제를 해결할 수 없다.
이때는 3가지 선택 방법이 있다.
- 마지막 커밋만 인정하기
사용자A의 내용은 무시하고 마지막에 커밋한 사용자B의 내용만 인정한다. - 최초 커밋만 인정하기
사용자A가 이미 수정을 완료했으므로 사용자B가 수정을 완료할 때 오류가 발생한다. - 충돌하는 갱신 내용 병합하기
사용자A와 사용자B의 수정사항을 병합한다.
기본은 마지막 커밋만 인정하기가 사용된다. 하지만 상황에 따라 최초 커밋만 인정하기가 더 합리적일 수 있다.
JPA가 제공하는 버전 관리 기능을 사용하면 손쉽게 최초 커밋만 인정하기를 구현할 수 있다.
충돌하는 갱신 내용 병합하기는 최초 커밋만 인정하기를 조금 더 우아하게 처리하는 방법인데 애플리케이션 개발자가 직접 사용자를 위해 병합 방법을 제공해야 한다.
다음 블로그 글에서 JPA에서 낙관적 락(Optimistic Lock)과 비관적 락(Pessimistic Lock)를 사용하는 법을 알아보자.
'JPA' 카테고리의 다른 글
JPA 1차 캐시와 2차 캐시 소개 (0) | 2022.01.26 |
---|---|
JPA에서 낙관적 락(Optimistic Lock)과 비관적 락(Pessimistic Lock) 사용 (0) | 2022.01.26 |
트랜잭션과 격리 수준 (0) | 2022.01.25 |
트랜잭션을 지원하는 쓰기 지연 (0) | 2022.01.25 |
JPA 배치 처리 (0) | 2022.01.25 |