본문 바로가기
CS

CS 스터디 (DB) 25 - DB 락에 대해 설명해주세요.

by gentle-tiger 2025. 5. 26.

 

 

공유 락(LS, Shared Lock)

- Read Lock라고도 하는 공유락은 트랜잭션이 읽기를 할 때 사용하는 락입니다.

- 데이터를 읽기만하기 때문에 같은 공유락 끼리는 동시에 접근이 가능하다는 장점이 있습니다 

- 다만, 동시에 읽을 수는 있으나, 변경은 안되며, 공유 락이 걸리면 배타 락을 걸 수 없습니다.

 

배타 락(LX, Exclusive Lock)

- Write Lock라고도 하는 베타락은 데이터를 변경할 때 사용하는 락입니다.

- 배타락은 트랜잭션이 완료될 때까지 유지되며, 베타락이 끝나기 전까지 어떠한 접근도 허용하지 않습니다.

- 다만, 배타 락이 걸리면 어떠한 락도 걸 수 없습니다.

 

 

데드락(Deadlock)

- 데드락은 두 개 이상의 트랜잭션이 서로가 소유한 자원을 기다리면서 무한히 대기하는 상태를 말합니다. 

- 데드락은 Coffman의 네 가지 조건이 모두 만족될 때 발생합니다. 

데드락 발생 조건 (Coffman 조건 4가지)

- 상호 배제(Mutual Exclusion): 자원은 하나의 트랜잭션만 점유할 수 있습니다.

- 점유 및 대기(Hold and Wait): 자원을 점유한 상태에서 다른 자원을 요청할 수 있습니다.

- 비선점(Non-Preemptive): 점유한 자원을 강제로 회수 불가합니다.

- 순환 대기(Circular Wait): 트랜잭션 간 자원 요청이 원형으로 연결되어 있습니다.

 

데드락 해결 방법 

타임아웃(Timeout)

- 이를 해결하기 위해 트랜잭션 타임아웃(timeout) 설정을 하여 일정 시간 자원 획득 실패시 트랜잭션을 자동 중단 시키는 것입니다. 

- Spring에서는 @Transactional(timeout = X) 또는 커넥션 풀(HikariCP)의 connectionTimeout 설정으로 구현합니다. 

@Service
@RequiredArgsConstructor
public class BankService {

    private final BankAccountRepository bankAccountRepository;

    @Transactional(timeout = 5) // 락 대기 시간 5초
    public void withdrawMoney(UUID accountId, BigDecimal withdrawAmount) {
        BankAccount account = bankAccountRepository.findByIdForUpdate(accountId)
                .orElseThrow(() -> new EntityNotFoundException("Account not found"));

        account.withdraw(withdrawAmount);
    }
}

 

 

결론 

데이터베이스 락은 트랜잭션 간 동시성 제어를 위해 사용하며, 공유락과 배타락이 있습니다. 공유락은 데이터를 읽을 때 사용하는 락으로 동시에 여러 트랜잭션이 읽기는 가능하지만 쓰기는 차단됩니다. 반면 배타락은 데이터를 수정할 때 사용하는 락으로 해당 자원에 대해 트랜잭션 읽기 쓰기 모두 차단합니다. 

다만 이러한 락 제어에 있어 두 개 이상의 트랜잭션이 서로 점유한 자원을 무한히 대기하면서 데드락이 발생할 수 있으며, 해결 방법으로는 트랜잭션에 타임아웃을 설정하여 일정 시간 내에 락을 획득하지 못하면 트랜잭션이 자동 중단되도록 하여 데드락을 회피할 수 있습니다,