낙관적 락(Optimistic Lock)과 비관적 락(Pessimistic Lock)의 기초
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에서 낙관적 락(Optimistic Lock)과 비관전 락(Pessimistic Lock) 사용
JPA 락 사용(Lock) 락은 다음 위치에 적용할 수 있다. EntityManager.lock(), EntityManager.find(), EntityManager.refresh() Query.setLockMode() (TypeQuery 포함) @NamedQuery // 조회 시 Locking Board board..
devbksheen.tistory.com