비선점(Optimistic) 잠금
- A 스레드 → 주문 애그리거트 조회
- B 스레드 → 주문 정보 변경
- A 스레드 → 주문 상태 변경
- 예를 들어 위와 같은 프로세스가 진행 되었을때 A 스레드는 예전 주문 정보를 보고 주문 상태를 변경 했을것이다.
- 이러한 문제들을 방지하기 위해 비선점 잠금을 사용한다.
- 비선점 잠금 방식은 잠금을 해서 동시에 접근하는것을 막는 대신 변경한 데이터를 실제 DBMS에 반영하는 시점에 변경 가능 여부를 확인하는 방식이다.
- 비선점 잠금을 구현하려면 애그리거트에 버전으로 사용할 숫자 타입의 프로퍼티를 추가해야 한다.
UPDATE aggtable SET version = version + 1, colx = ?, coly = ?
WHERE aggid = ? and version = 현재버전
- 이 쿼리는 수정할 애그리거트와 매핑되는 테이블의 버전 값이 현재 애그리거트 버전과 동일한 경우에만 데이터를 수정한다.
- 수정 성공 시 버전 값을 1증가시킨다.
- 따라서, 다른 트랜잭션이 먼저 데이터를 수정해서 버전 값이 바뀌면 데이터 수정에 실패하게 된다.
![https://s3-us-west-2.amazonaws.com/secure.notion-static.com/c6988da5-183a-4320-9fbc-5562a411d01a/Untitled.png](https://s3-us-west-2.amazonaws.com/secure.notion-static.com/c6988da5-183a-4320-9fbc-5562a411d01a/Untitled.png)
- JPA는 버전을 이용한 비선점 잠금 기능을 지원한다.
- 버전으로 사용할 필드에 @Version 어노테이션을 붙히고 매핑되는 테이블에 버전을 저장할 컬럼을 추가 하기만 하면 된다.
@Entity
@Table(name = "purchase_order")
@Access(AccessType.FIELD)
public class Order {
@EmeddedId
private OrderNo orderNo;
@Version
private long version;
...
}
- 응용 서비스를 버전에 대해 알 필요가 없고, 알맞은 비지니스 로직만 구현하면 된다.
- 실행 결과로 변경된 행의 개수가 0이면 OptimisticLockingFailureException을 발생되고 트랜잭션이 종료된다.
비선점 잠금 방식을 위한 View