728x90
반응형
SMALL
학습내용
- 락(Lock) 개념
- 비관적 락 vs 낙관적 락
- JPA에서의 락 종류와 사용방법
- 실습
학습정리
1. Lock
- 데이터베이스에서 동시 실행되는 트랜잭션 간의 충돌을 방지하고, 데이터 정합성을 보장하기 위해 특정 자원에 대한 접근을 제어하는 메커니즘
-> 즉, 다른 트랜잭션이 특정 데이터에 접근하지 못하도록 잠그는 것
-> 락은 막는 행위가 아니라 락은 획득하는것, 락이 끝나면 반납 - 중요성
- 동시성제어 : 동시에 실행 될 때 데이터의 일관성과 정확성을 보장
- 데이터 정합성 유지 : 충돌 상황에서도 데이터가 항상 일관된 상태를 유지
- 시스템 안정성 보장 : 트랜잭션의 원자성을 보장하며 작업 도중 발생하는 오류를 최소화
2. 비관적 락 vs 낙관적 락
비관적 락
개념
- 데이터 충돌이 자주 발생할 것이라고 가정하고, 락을 걸어 다른 트랜잭션이 접근하지 못하게 막음.
- 트랜잭션이 끝날 때까지 다른 트랜잭션을 대기(block)시킴
동작 방식
- 데이터를 수정하려는 트랜잭션이 락을 걸어 다른 트랜잭션이 접근하지 못하게 함.
- 트랜잭션이 끝날 때까지 다른 트랜잭션은 대기.
- 트랜잭션이 COMMIT 또는 ROLLBACK되면 락 해제.
구현방식
“SELECT … FOR UPDATE” 를 사용하여 데이터를 읽으면서 동시에 락을 걸어 수정이 완료 될 때까지 접근을 차단
-- 트랜잭션 A: 재고 감소 처리 START TRANSACTION; SELECT stock FROM products WHERE id = 1 FOR UPDATE; -- 해당 행에 Exclusive Lock 적용 UPDATE products SET stock = stock - 1 WHERE id = 1; COMMIT; -- 트랜잭션 B: 재고 접근 시도 START TRANSACTION; SELECT stock FROM products WHERE id = 1 FOR UPDATE; -- 트랜잭션 A가 커밋될 때까지 대기 UPDATE products SET stock = stock - 1 WHERE id = 1; COMMIT;
낙관적 락
개념
- 데이터 충돌이 자주 발생하지 않을 것이라고 가정하고, 락을 걸지 않음.
- 대신, 데이터 변경 시 충돌을 감지하여 실패한 경우 다시 시도하도록 함.
동작방식
- 데이터를 조회할 때 버전(Version) 또는 타임스탬프(Timestamp)를 함께 조회.
- 데이터를 수정할 때 기존 버전과 비교.
- 버전이 변경되지 않았다면 업데이트 성공, 버전이 변경되었다면 충돌 발생 → 업데이트 실패 → 다시 시도.
구현방식
버전(Version) 컬럼을 사용하여 충돌 감지.
//version 컬럼 추가 //실무에서는 버전관리는 좀더 유니크한 값으로 설정 //예시) 날짜를 해시값으로 ALTER TABLE products ADD COLUMN version INT DEFAULT 0; //데이터 수정 //트랜잭션 A가 데이터를 조회 START TRANSACTION; SELECT stock, version FROM products WHERE id = 101; -- stock: 10, version: 0 //version 값이 일치하면 version과 값을 업데이트 처리 UPDATE products SET stock = stock - 1, version = version + 1 WHERE id = 101 AND version = 0; COMMIT; //트랜잭션 B가 데이터를 조회 START TRANSACTION; SELECT stock, version FROM products WHERE id = 101; -- stock: 9, version: 1 //version 값이 일치하지 않으므로 롤백 //재시도 로직이 필수로 들어가야함 UPDATE products SET stock = stock - 1, version = version + 1 WHERE id = 101 AND version = 0; -- 실패 ROLLBACK;
낙관적 락 vs 비관적 락 비교 정리
구분 비관적 락 (Pessimistic Lock) 낙관적 락 (Optimistic Lock) 개념 데이터를 선점하여 다른 트랜잭션의 접근을 차단 충돌 가능성을 가정하며 작업 후 충돌 여부를 판단 적용 환경 충돌 가능성이 높은 환경 충돌 가능성이 낮은 환경 장점 데이터 손상을 방지하며 안정성이 높음 자원 점유 시간이 적고 성능이 뛰어남 단점 데드락 위험과 성능 저하 발생 가능 충돌 발생 시 작업 재시도로 인해 성능 저하 가능 구현 방식 SELECT ... FOR UPDATE 사용 버전 컬럼을 활용하여 충돌 여부 판단
3. JPA에서 락의 종류와 사용방법
비관적 락 (Pessimistic Lock)
비관적 락의 종류
락 종류 설명 SQL 문 PESSIMISTIC_READ 다른 트랜잭션이 읽기는 허용하지만 수정은 허용하지 않음. SELECT ... LOCK IN SHARE MODE와 유사 LOCK IN SHARE MODE PESSIMISTIC_WRITE 읽기와 쓰기 모두 차단하여 다른 트랜잭션이 해당 데이터에 접근하지 못하도록 막음. SELECT ... FOR UPDATE와 유사 FOR UPDATE PESSIMISTIC_FORCE_INCREMENT 버전 필드를 강제로 증가시켜 낙관적 락과 유사하게 버전 충돌을 유도. 주로 버전 충돌 확인에 사용됨. (DB에 따라 다름) 기본적으로 PESSIMISTIC_WRITE 을 사용
사용방법
@Repository public interface ProductRepository extends JpaRepository<Product, Long> { ... //@Lock 어노테이션을 사용해서 비관적 락 적용 @Lock(LockModeType.PESSIMISTIC_WRITE) @Query("SELECT p FROM Product p WHERE p.id = :id") Optional<Product> findByIdForUpdate(@Param("id") Long id); @Lock(LockModeType.PESSIMISTIC_WRITE) Optional<Product> findFirstByName(String name); }
낙관적 락 (Optimistic Lock)
낙관적 락의 종류
락 종류 설명 OPTIMISTIC 트랜잭션이 커밋될 때 버전 필드를 확인하여 충돌 여부를 검사함. 기본적인 낙관적 락 방식 OPTIMISTIC_FORCE_INCREMENT 트랜잭션 시작 시 버전 필드를 강제로 증가시켜 이후 발생하는 모든 충돌을 감지함. 주로 데이터 갱신 시 명시적 충돌 확인 READ 데이터를 읽을 때 버전을 검사하여 충돌을 방지하는 읽기 전용 락 (낙관적 읽기 락) 기본적으로 OPTIMISTIC 사용
사용방법
//해당 엔티티에 version 추가 @Entity @Getter @DynamicInsert @DynamicUpdate @NoArgsConstructor @Table(name = "products") @FieldDefaults(level = AccessLevel.PRIVATE) public class Product { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) Long id; ...생략 //비관적락 버전추가 어노테이션 @Version Integer version; ..생략 } //리포지토리에서 사용방법 public interface ProductRepository extends JpaRepository<Product, Long> { @Lock(LockModeType.OPTIMISTIC) Optional<Product> findFirstByNameOrderById(String name); }
728x90
반응형
LIST
'TIL' 카테고리의 다른 글
6_5.데이터베이스 기반 작업 큐 실습 (0) | 2025.02.04 |
---|---|
6_4.CAP 이론과 일관성 전략 (0) | 2025.02.04 |
6_2.트랜잭션 격리 수준 이해 및 실습 (0) | 2025.02.01 |
6_1.동시성 문제 개념 및 사례 분석 (0) | 2025.01.27 |
5_5.MyBatis 활용 (0) | 2025.01.24 |