본문 바로가기

개발중/Java Persistence API (JPA)

JPA ( Java Persistence API ) Transaction

728x90
반응형

🧐 트랜잭션이란 ?

 

DB 상태를 변환시키는 하나의 논리적 기능을 수행하기 위한 작업의 단위 또는 한꺼번에 모두 수행되어야 할 일련의 연산들

 

 

🧐 JPA 트랜잭션 격리수준

 

트랜잭션이 보장해야하는 ACID 중 격리성과 관련된 내용인데  격리성을 완벽히 보장하려면 동시성 처리 성능이 매우 나빠진다.

이런 문제로 인해 ANSI 표준은 트랜잭션의 격리 수준을 4단계로 나누어 정의했다.

 

  1. Atomicity; 원자성
    1. 트랜잭션 내의 작업들은 모두 성공 또는 모두 실패한다.
  2. Consistency; 일관성
    1. 모든 트랜잭션은 일관성 있는 DB 상태를 유지한다. 
    2. (ex: DB의 무결성 제약 조건 항상 만족)
  3. Isolation; 격리성
    1. 동시에 실행되는 트랜잭션들은 서로 영향을 미치지 않는다. 
    2. (ex: 동시에 같은 데이터 수정 X)
  4. Durability; 지속성
    1. 트랜잭션이 성공적으로 끝나면 그 결과는 항상 기록되어야 한다.

 

🧐 트랜잭션 관리 포인트 3

낮은 단계의 트랜잭션 고립화 수준 이용시 발생하는 현상 3가지

 

  1. Nonrepeatble Read
    1. 트랜잭션이 수행중인데 다른 트랜잭션이 읽고 있는 데이터를 수정해서 쿼리 결과가 달라지는 것.
    2. 한 트랜잭션 내에서 같은 쿼리를 두 번 수행할 때 
      그 사이에 다른 트랜잭션이 값을 수정 또는 삭제함으로써 
      두 쿼리의 결과가 상이하게 나타나는 비 일관성 발생한다.
  2. Phantom Read
    1. 동일한 쿼리가 다른 값을 반환하는 것 
    2. 한 트랜잭션 안에서 일정 범위의 레코드를 두 번 이상 읽을 때, 
      첫 번째 쿼리에서 없던 레코드가 두 번째 쿼리에서 나타나는 현상. 
      이는 트랜잭션 도중 새로운 레코드가 삽입되는 것을 허용하기 때문에 나타난다.
  3. Dirty Read
    1. 변경된 데이터가 아직 미완성인데 다른 트랜잭션에서 읽어가는 것.
    2. T1 트랜잭션에서 읽기하고 실행이 끝나지 않은 상태에서 
      T2 트랜잭션에 의해 변경된 사항을 보게 되는 경우를 dirty read 라고 한다. 
      만약 T2 트랜잭션에서 그 변경 사항을 rollback하면 
      그 데이터를 읽은 T1 트랜잭션은 Dirty 데이터를 가지고 있는 것이다.

 

🧐 격리수준

 

아래로 내려 갈수록 동시성이 높아지는 대신 속도가 느려진다.  ( lv.0 -> lv.3)

위로 올라 갈수록 동시성이 떨어지는 대신 속도가 빨라진다.  (lv.3 -> lv.0)

 

  1. READ UNCOMMITED (lv.0)
    • 커밋되지 않은 데이터도 읽을 수 있음
      • A트랜잭션에서 데이터를 변경하려다 에러가 발생해서 Rollback을 했다고 치면 A트랜잭션이 실행되는 동안 데이터를 요청한 B 트랜잭션은 잘못된 데이터를 읽고 있을 수가 있다. Dirty Read, Dirty Write이 가능함
      • Dirty Read는 방지 X, Noorepeatable read방지 X, Phantom Read 방지 X
  2. READ COMMITED (lv.1)
    • 커밋된 데이터만 불러온다. (= 반복해서 같은 데이터를 불러올 수 없다) 
      • SELECT 문장이 수행되는 동안 해당 데이터에 Shared Lock(읽기 가능, 변경 불가)이 걸리는 레벨
        • 어떠한 사용자가 A라는 데이터를 B라는 데이터로 변경하는 동안 다른 사용자는 해당 데이터(B)에 접근할 수 없습니다.
      • Dirty Read 방지 O , Non-Repeatable Read 방지 X
  3. REPEATABLE READ (lv.2)
    • 트랜잭션 동안에는 한번 조회한 데이터를 계속 조회해도 같은 데이터가 나오지만, 만약 다른 트랜잭션에서 데이터를 추가한 경우 기존 트랜잭션에서 반복 조회하면 결과 집합이 새로 추가된 데이터를 포함한 결과를 가져오게 된다.  
      • Dirty Read 방지 O,  Non-Repeatable Read 방지 O, Phantom Read 방지 X 
  4. SERIALIZABLE (lv.3)
    • 모든 트랜잭션을 순서대로 실행한다.
    • Dirty Read 방지 O,  Non-Repeatable Read 방지 O, Phantom Read 방지 O

 

 

JPA를 사용하면 격리 수준을 READ_COMMITED로 가정하는데

만약 일부 로직에 더 높은 격리 수준이 필요하면 비관적 락과 낙관적 락 중에 선택을 하여 사용해야 한다.

JPA의 추천하는 전략은 READ_COMMITTED  + 낙관적 락 이다.

 

  • 낙관적 락
    • 트랜잭션 대부분은 충돌이 발생하지 않는 다고 가정하며, JPA가 제공하는 버전 관리 기능을 사용한다. (어플리케이션 단 레벨)
    • 트랜잭션을 커밋하기 전까지는 트랜잭션의 충돌을 알 수 없다는 특징이 있다.
    • JPA에서 제공하는 @Version 어노테이션을 사용하며, 최초 커밋만 인정되어 두번째 커밋에선 예외를 발생시킨다. 
  • 비관적 락
    • 트랜잭션 간 충돌이 발생한다고 가정하여 우선 락을 건다, 데이터베이스가 제공하는 락 기능을 사용한다. 
    • 데이터를 수정하는 즉시 트랜잭션 충돌을 감지하며 예외를 발생시킨다.
    • 비관적 락을 사용하면 락을 획득할 때까지 트랜잭션이 대기한다. 무한정 기다릴 수 없으므로 타임아웃 시간을 줄 수 있다.

 

JPA의 추천하는 전략은 READ_COMMITTED  + 낙관적 락 이다.

728x90
반응형