pessimistic lock
DB에 직접 락(lock)을 거는 방법
@Lock(PESSIMISTIC_WRITE)
@Query("select s from Stock s where s.id = :id")
Stock findByIdWithPessimisticLock(Long id);
Spring Jpa 에서 findById 대신에 @Lock 을 사용한 메서드를 사용하면 된다.
제일 간편하나 Transaction이 필요하다.
optimistic lock
version 처리를 하여 사용하는 방법
@Entity 에 @Version 값이 있어야 한다. Transaction이 필요없다.
그러므로 에러 해결을 직접 해주어야 한다
while (true) {
try {
stockService.decrease_optimistic_lock(id, quantity);
break;
} catch (Exception e) {
Thread.sleep(58);
}
}
named lock
MySql 에서 get_lock() 함수를 사용하여 직접 락을 걸고 release_lock() 으로 락을 풀어 사용하는 방법.
많이 쓰이는 방법은 아닌 것 같다 (아무래도 직접 락을 걸고 해제한다는 게 에러가 발생할 확률을 높힐 것 같다...)
try {
stockRepository.getLock(id.toString());
Stock stock = stockRepository.findById(id).orElseThrow(() -> new
RuntimeException("아이템이 존재하지 않습니다"));
stock.decrease(quantity);
stockRepository.saveAndFlush(stock);
} finally {
stockRepository.releaseLock(id.toString());
}
@Query(value = "select get_lock(:key, 3000)", nativeQuery = true)
void getLock(String key);
@Query(value = "select release_lock(:key)", nativeQuery = true)
void releaseLock(String key);