한 주문 애그리거트에 대해 운영자와 고객이 동시에 애그리거트를 수정한다면?

수정하지 못하게 막는 방식
접근, 수정 잠금잠금을 구할 때 최대 대기 시간 지정
Map<String, Object> hints = new HashMapo<>;
hints.put("javax.persistence.lock.timeout", 2000);
Order order = entityManager.find(
Order.class, orderNo, LockModeType.PESSIMISTIC_WRITE, hints);
DBMS에 따라 힌트가 적용되지 않을 수도 있다.
public interface MemberRepository extends Repository^ember^ Memberld> {
@Lock(LockModeType.PESSIMISTIC_WRITE)
@QueryHints({
@QueryHint(name = "javax.persistence.lock.timeout", value = "2000")
})
@Query("select m from Member m where m.id = :id")
Optional<Member> findByIdForUpdate(@Param("id") Memberld memberld);
DBMS에 따라 쿼리별로 대기시간을 정할 수 있고, 커넥션 단위로 대기시간을 정할 수 있다.

동시에 같은 컬럼을 갱신하는 경우만 막아준다.실제 DBMS에 반영하는 시점에 변경 가능 여부를 확인하는 방식이다.version 컬럼을 추가해 현재 버전과 일치하는지 체크한다.
- 수정 시 version을 올린다.
UPDATE aggtable SET version = version + 1, colx = ?, coly = ?
WHERE aggid = ? and version = 현재버전
예시 >
- 주문 row에 version 칼럼을 둠.
- 조회 시 version=1 → 운영자가 update할 때 where id=? and version=1
- 고객이 먼저 update하면 version=2가 되므로, 운영자의 update는 영향 row=0 → 실패 감지 가능
- 이 실패를 잡아 "데이터가 변경되었으니 다시 조회 후 처리하세요"로 안내하면 해결

첫 번째 트랜잭션에서 오프라인 잠금을 선점하고 마지막 트랜잭션에서 잠금을 해제한다.
잠금 유효 시간을 가져야 한다.public interface LockManager {
Lockld tryLock(String type. String id) throws LockException;
void checkLock(LockId lockld) throws LockException;
void releaseLock(LockId lockld) throws LockException;
void extendLockExpiration(LockId lockld, long inc) throws LockException;
}create table locks (
'type' varchar(255),
id varchar(255),
lockid varchar(255),
expiration_time datetime, // 잠금 유효 시간 보관
primary key ('type', id)
) character set utf8;
create unique index locks idx ON locks (lockid);