본 글을 DB Lock에 대해서 공부한 지식을 정리한 글입니다.
비관적 락의 문제점
비관적 락(Pessimistic Lock)을 JPA를 통해서 확인을 하다가 궁금한점이 생겼는데, DB Lock의 필요성 중 업데이트 손실이 있습니다.업데이트 손실은 두 개 이상의 트랜잭션이 동일한 데이터를 읽고, 그 데이터를 기반으로 수정 작업을 수행할 때 발생합니다.
이러한 문제를 해결하기 위해서 DB Lock을 통하여 접근제어를 하면 데이터 무결성 문제를 해결할 수 있습니다.
그러나 DB Lock만 사용한다고 해서 만능은 아닙니다. 그 이유는 위의 포스팅에서 확인한 "비관적 락"을 사용하여 동시성 제어를 확인했는데, 이 때 같이 나타난 현상이 바로 "업데이트 손실(Lost update)"입니다.
업데이트 손실(Lost Update)이 비관적 락을 사용하더라도 나타날 수 있는 이유는 주로 트랜잭션의 설계와 데이터 접근 방식에 있습니다. 비관적 락을 사용하더라도 특정 조건 하에서는 업데이트 손실이 발생할 수 있습니다.
1. 업데이트 순서에 따른 문제
비관적 락은 동시성 문제를 줄이기 위해 사용되며, 동시에 두 트랜잭션이 동일한 데이터를 수정하려고 할 때 하나의 트랜잭션이 완료될 때까지 다른 트랜잭션이 기다리도록 만듭니다. 그러나, 비관적 락은 순서대로 트랜잭션이 실행되도록 보장하지 않으며, 단지 동시에 수정하지 못하게 할 뿐입니다.
코드의 시나리오를 다시 보면,
- Thread2가 먼저 Item을 읽고, 수량을 10 ➡️ 30으로 업데이트합니다.
- Thread1이 그 후 Item을 읽고, 수량을 10 ➡️ 20으로 업데이트합니다.
각각의 스레드가 수량을 업데이트하기 전에 다른 스레드가 수량을 먼저 변경했는지 확인하는 메커니즘이 없기 때문에, Thread1이 Thread2가 변경한 값을 덮어쓰는 업데이트 손실이 발생합니다.
2. 비관적 락의 제한
비관적 락은 다른 트랜잭션이 동시에 동일한 데이터를 읽거나 수정하지 못하도록 막아주지만, 각 트랜잭션이 실행되는 순서에 대한 정보를 제공하지 않으며, 각 트랜잭션이 이미 수정된 데이터를 읽고 있는지도 보장하지 않습니다.
이 상황에서의 업데이트 손실은 Thread2가 수량을 30으로 업데이트한 후, Thread1이 여전히 10이라는 초기 수량을 기반으로 작업을 수행한 결과 발생한 것입니다.
Thread1은 30으로 업데이트된 값을 모르고, 10에서 20으로 변경했기 때문에, 결국 20이라는 값이 최종적으로 저장됩니다.
결론적으로 비관적 락을 사용해도 업데이트 손실이 발생할 수 있습니다.
이는 비관적 락이 트랜잭션 간 동시성 문제를 해결하지만, 업데이트 순서와 데이터의 최신 상태를 보장하지 않기 때문입니다.
트랜잭션이 먼저 읽은 데이터를 기준으로 업데이트하면, 나중에 실행된 트랜잭션이 앞선 트랜잭션의 변경을 덮어쓸 수 있어 업데이트 손실이 발생합니다.
이 문제를 해결하려면, 두 트랜잭션이 서로의 작업을 덮어쓰지 않도록 낙관적 락(Optimistic Lock)을 사용하거나, 버전 관리를 통해 트랜잭션 간 충돌을 감지하는 방법을 사용할 수 있습니다.
'TIL,일일 회고' 카테고리의 다른 글
[TIL, 일일회고] 2024.08.23 - JPA Entity 클래스 간의 참조: 의존성 주입이 아닌 FK 관계를 위한 설계 (0) | 2024.08.23 |
---|---|
[TIL, 일일 회고] 2024.08.22 - assertThrows란 무엇일까❓: 예외를 테스트하는 효과적인 방법 (0) | 2024.08.22 |
[TIL, 일일 회고] 2024.08.20 - Referer헤더란❓ (0) | 2024.08.20 |
[TIL, 일일 회고] 2024.08.19 - 출처란 무엇일까❓ (0) | 2024.08.19 |
[TIL, 일일 회고] 2024.08.18 - Spring boot Actuator란 무엇일까❓ (0) | 2024.08.18 |