동시성 문제 - 데이터베이스와 JPA (Part 2)

web | 06 March 2020

Tags | concurrency architecture enterprise database jpa

시리즈

Part 1 : 동시성 문제 - 일반론

Part 2 : 동시성 문제 - 데이터베이스와 JPA (NOW)

Part 3 : 동시성 문제 - 비즈니스 애플리케이션

앞선 글에서 특정 시스템에 종속되지 않는 동시성 문제의 일반론에 대해서 정리해보았습니다.

이번 글에서는 데이터베이스 시스템과 JPA 에서는 동시성 문제를 어떻게 제어하는지 알아보겠습니다.

데이터베이스의 동시성 제어

데이터베이스 시스템에서 세션은 “트랜잭션 (Transaction)” 입니다.

Transaction 의 특성 4가지 ACID 중 Isolation 은 바로 트랜잭션의 동시성 제어와 깊이 관련이 있습니다.

바로 이 Isolation 의 정도를 나타내는 Isolation Level 4가지가, 데이터베이스 동시성 제어의 핵심입니다.

각각의 레벨에 따라 “일관성 없는 읽기” 와 “손실되는 업데이트” 가 해결되는지 확인해보겠습니다.

Isolation Level “일관성 없는 읽기” 해결되나? “손실되는 업데이트” 해결되나? 일반론 “정확성과 활동성”
Serializable O O 비관적 잠금으로 두 문제 모두 해결 정확성은 높으나 활동성 매우 낮음
Repeatable Read O X 복사본 사용으로 “일관성 없는 읽기” 해결 적절한 타협. 대부분 DBMS 의 기본값.
Read Committed X X 복사본을 사용하지 않아서 읽기에 일관성이 없음 활동성 (동시성) 이 매우 높음

Read Uncommitted 를 논외로 한 이유는 RDBMS 표준에서는 격리수준으로 인정하지 않기 때문입니다.

JPA 의 동시성 제어

JPA 시스템에서의 세션은 하나의 JPA Transaction 입니다. JPA에서의 읽기 쓰기 동시성은 Entity 객체와 관련이 있습니다.

Entity 객체를 한번 조회하면 JPA 의 영속성 컨텍스트 (Persistance Context) 에 캐시되기 때문에, 세션 (JPA Transaction) 내에서의 “일관성 없는 읽기” 의 문제는 없습니다.

그렇다면 JPA 는 “손실되는 업데이트” 문제를 어떻게 제어할까요? JPA 는 Entity 단위의 낙관적 잠금과 비관적 잠금을 제공합니다.

JPA 낙관적 잠금

img-name

JPA 의 버전 관리 기능 ( @Version )을 이용해 Entity 의 버전을 관리해 낙관적 잠금을 구현합니다. Application Level 에서의 잠금이며, 낙관적 잠금이므로 두번째 세션이 Write 하기 전까지는 충돌을 알 수 없습니다.

활동성은 높일 수 있지만, 잘 진행되고 있던 프로세스가 변경 사항을 저장하려고 할 때 까지 프로세스의 성패를 예측할 수 없다는 것이 단점입니다.

JPA 비관적 잠금

img-name

데이터베이스가 제공하는 lock 기능을 이용해 엔티티를 영속 상태로 올릴 때부터 다른 세션에서 조회하지 못하도록 잠금을 걸어둡니다. ( select for update 구문이라고 생각할 수 있습니다. )

역시 비관적 잠금인만큼, 활동성은 매우 저하되지만 정확성과 세션의 성공은 보장됩니다.

💡 다음 글 : 동시성 문제 - 비즈니스 애플리케이션 (Part 3)