백엔드 멘토링

Transaction이란?

piedra_de_flor 2023. 9. 23. 15:52

Transaction이란?

Transaction이란 데이터의 상태를 변화시키기 위한 작업들의 집합 단위이다.

 

Spring에서 @Transactional의 동작과정

@Transaction이 적용되어 있을 경우 해당 클래스에 대한 트랜잭션 기능이 적용된 프록시 객체가 생성된다.

이 프록시 객체는 @Transactional이 포함된 해당 메서드가 호출될 경우 트랜잭션을 시작하고, 정상 여부에 따라 Commit 또는 Rollback을 수행한다.

정상여부는 default로 RuntimeException이 발생했는지 안했는지의 기준으로 결정된다.

 

 

Transaction의 특징

Transaction은 ACID라고 불리는4가지의 특징이 있는데

  • 원자성 (Atomicity) : 트랜잭션이 데이터베이스에 모두 반영되던가, 아니면 전혀 반영되지 않아야 한다는 것
  • 일관성 (Consistency) : 트랜잭션의 작업 처리 결과가 항상 일관성이 있어야 한다는 것
    트랜잭션이 진행되는 동안에 데이터베이스가 변경 되더라도 업데이트된 데이터베이스로 트랜잭션이 진행되는것이 아니라, 처음에 트랜잭션을 진행 하기 위해 참조한 데이터베이스로 진행된다. 이렇게 함으로써 각 사용자는 일관성 있는 데이터를 볼 수 있는 것이다
  • 독립성 (Isolation) : 어떤 하나의 트랜잭션이라도, 다른 트랜잭션의 연산에 끼어들 수 없다는 점을 가리킨다 하나의 특정 트랜잭션이 완료될때까지, 다른 트랜잭션이 특정 트랜잭션의 결과를 참조할 수 없다
  • 지속성 (Durability) : 트랜잭션이 성공적으로 완료됬을 경우, 결과는 영구적으로 반영되어야 한다는 점

이 4가지 특징은 Transaction이 가져야 할 성질들이지만, 너무 이 특징들이 잘 지켜졌을 경우에는 문제점이 발생할 수 있다.

특히 독립성 (Isolation) 부분에서 동시성 문제가 발생하는데,

 

 

Transaction 동시성문제

  • Dirty Read : 트랜잭션이 커밋되지 않았는데도 다른 트랜잭션에서 커밋되지 않은 데이터를 읽는 현상
  • Non-repetable Read : 한 트랜잭션 내의 SELECT 결과가 다르게 읽히는 현상 (선행 트랜잭션에서 첫번째로 수행한 SELECT와 두번째로 수행한 SELECT 결과가 다르게 읽히는 현상, 후행 트랜잭션에서 해당 데이터를 수정 또는 삭제할 때 나타나는 현상)
  • Phantom Read : 한 트랜잭션 내에서 같은 쿼리를 두 번 실행했을 경우, 첫 번째 쿼리에서 없던 유령(Phantom) 레코드가 두 번째 쿼리에서 나타나는 현상을 말한다. (후행 트랜잭션에서 선행 트랜잭션에서 조회한 조건과 일치하는 데이터를 추가했을 경우 나타나는 현상)

여기서 Non-repetable Read 와 Phantom Read가 헷갈릴 수 있는데,

Phantom Read 는 기존 조회결과에 없던 것이 생겨나거나 없어지는 현상을 의미하고

Non-repetable Read 는 기존 조회결과와 다른 결과값이 반환된다는 의미이다.

 

이 문제들을 해결하기 위해 Spring에서는 @Transactional에 isolation이라는 옵션을 추가해놨다.

이어서 @Transactional의 옵션 2가지에 대해 알아보겠다.

 

 

 

 

Spring @Transactional의 옵션 : propagation, isolation

1. propagation

  • 특정 트랜잭션 동작 도중 또다른 트랜잭션을 호출(실행) 하는 상황에서 트랜잭션을 어떻게 동작시킬 것인지 결정하는 방식 (ex. 트랜잭션이 적용된 메서드에서 트랜잭션이 적용된 또다른 메서드를 호출하는 상황)
  • 호출 당한 트랜잭션 입장에서 호출한 쪽의 트랜잭션을 그대로 사용할 수도 있고, 새롭게 트랜잭션을 생성할 수도 있음
  • 이러한 트랜잭션 관련 설정은 @Transactional의 propagation 속성을 통해 지정가능

 

사용 방법은 @Transactional(propagation = Propagation.SUPPORTS)의 형태로 사용된다.

 

2. isolation

  • Isolation Level은 동시 트랜잭션이 수행될때 다른 트랜잭션이 동일한 데이터에 대해서 어떻게 보일지에 대한 범위를 나타낸다.
  • Transaction의 동시성 문제를 해결하기 위한 옵션

 

사용 방법은 @Transacional(isolation = Isolation.READ_COMMITED) 의 형태로 사용된다.

 

@Transactional의 isolation 옵션은 트랜잭션의 격리 수준을 지정하는 옵션으로

isolation의 격리 수준을 높힐 경우 데이터의 일관성은 향상될 수 있으나, 성능의 저하가 일어난다.

왜냐하면 하나의 트랜잭션이 수행 중 일때 격리 수준이 높을 수록 다른 트랜잭션을 수행하는데 제약이 있을 수 있기 때문이다.