1. 동시성이란?

동시성 : 하나의 데이터를 여러 사용자가 동시에 수정하거나 읽는 상황

→ 기본적으로 컴퓨터의 연산이 빨라 동시에 같은 데이터에 접근할 일이 거의 없지만, 가끔 여러 사람이 같은 데이터에 접근하는 일이 발생함

경쟁 상태(Race Condition) : 동일 자원을 누가 먼저 처리하느냐에 따라 결과가 달라지고 데이터 일관성이 깨지는 문제가 발생

<aside> 💡

왜 DB에서 막을 수 없을까?

DB는 요청을 독립된 트랜잭션으로 처리하기 때문에, 지금 다른 요청이 같은 데이터를 수정하고 있는지 모름

</aside>

동시성 문제를 해결하는 방법 : 접근 제어(조정)

구분 비관적 락 낙관적 락
접근 방식 먼저 잠그고 나중에 작업 잠그지 않고 나중에 충돌을 확인
처리 방식 다른 트랜잭션은 대기 상태 동시에 접근 가능, 충돌 시 예외 발생
성능 느리지만 안전함 빠르지만 충돌 시 재시도 필요
사용 예 민감한 데이터
(재고 차감, 출금 등) 엄청 중요하진 않은 데이터
(게시글 수정, 프로필 변경 등)

2. 비관적 락(Pessimistic Lock)

비관적 락(Pessimistic Lock) : “동시에 다른 사용자가 같은 데이터를 수정할 것이다”라고 비관적으로 가정하고 먼저 데이터를 잠그는 방식

→ 한 트랜잭션이 데이터를 수정하는 동안, 다른 요청은 락이 해제될 때까지 대기 상태가 됨

JPA에서 비관적 락 구현 방법 : Repository에 @Lock 어노테이션 사용

public interface AccountRepository extends JpaRepository<Account, Long> {

    @Lock(LockModeType.PESSIMISTIC_WRITE) // 쓰기에 대한 Lock 사용
    @Query("SELECT a FROM Account a WHERE a.id = :id")
    Account findByIdForLOCK(@Param("id") Long id);

}
락 타입 설명
PESSIMISTIC_READ 읽기 Lock 사용
PESSIMISTIC_WRITE 쓰기 Lock 사용

비관적 락 사용 시 주의사항