티스토리 뷰

트랜잭션이란


  • 데이터베이스의 상태를 변경시키는 하나의 논리적 기능을 수행하는 작업의 단위

 

@Transactional


  • 스프링에서 트랜잭션 기능을 제공하는 어노테이션

  • 선언형 트랜잭션

  • @Transactional은 클래스, 인터페이스, 메서드 위에 적용 가능

 

@Transactional 동작 원리


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

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

  • 정상여부는 default로 RuntimeException이 발생했는지 안했는지의 기준으로 결정됨

  • RuntimeException 외 다른 Exception(ex. SQLException) 에도 트랜잭션 롤백처리를 적용하고 싶으면 @Transactional의 RollbackFor 속성을 활용할 수 있음 

 

 

트랜잭션의 Propagation(전파)


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

 

@Transactional의 propagation 속성


  • REQUIRED : default propagation, 트랜잭션이 없으면 새로 생성하고, 이미 시작된 트랜잭션이 있으면 해당 트랜잭션을 사용함.

  • REQUIRES_NEW : 항상 새로운 트랜잭션을 시작. 즉, 이전에 시작되어 실행중인 트랜잭션에 상관없이 항상 새로운 트랜잭션을 만들어 시작시킴.

  • NOT_SUPPORTED : 현재 진행중인 트랜잭션이 있어도 사용x, 무시함. 트랜잭션이 없으면 그냥 진행, 새로 생성x. (여러 메서드 동작 시 특정 메서드만 트랜잭션 적용을 제외시키기 위함) 

 

트랜잭션의 isolation(격리)


  • 트랜잭션에서 일관성이 없는 데이터를 허용하도록 하는 수준

  • 여러 트랜잭션을 순차적으로 수행시킨다면 성능이 매우 안좋을 것

  • 즉, 여러 트랜잭션들을 동시에 수행시키면서 데이터의 정합성을 유지시킬 수 있는 적절한 격리 수준이 필요함

 

트랜잭션의 동시성 문제


  • Dirty Read : 트랜잭션이 커밋되지 않았는데도 다른 트랜잭션에서 커밋되지 않은 데이터를 읽는 현상

  • Non-repetable Read : 한 트랜잭션 내의 SELECT 결과가 다르게 읽히는 현상 (선행 트랜잭션에서 첫번째로 수행한 SELECT와 두번째로 수행한 SELECT 결과가 다르게 읽히는 현상, 후행 트랜잭션에서 해당 데이터를 수정 또는 삭제할 때 나타나는 현상)

  • Phantom Read : 한 트랜잭션 내에서 같은 쿼리를 두 번 실행했을 경우, 첫 번째 쿼리에서 없던 유령(Phantom) 레코드가 두 번째 쿼리에서 나타나는 현상을 말한다. (후행 트랜잭션에서 선행 트랜잭션에서 조회한 조건과 일치하는 데이터를 추가했을 경우 나타나는 현상)

 

@Transactional의 isolation level


  • READ_UNCOMMITED : 해당 트랜잭션에서 커밋되지 않은 데이터를 다른 트랜잭션이 접근할 수 있도록 허용함

  • READ_COMMITED : 해당 트랜잭션으로부터 커밋된 확정 데이터만 다른 트랜잭션에서 접근 허용 (외부 트랜잭션에서 해당 데이터를 삭제, 수정할 경우 Non-Repeatable-Read를 막을 수 없음)

  • REPEATABLE_READ : 한 트랜잭션 내에서 실행되는 모든 같은 SELECT문의 결과가 같도록 조회할 수 있는 격리수준 (선행 트랜잭션에서 SELECT문에 사용된 데이터들에 Shared Lock을 걸어 후행 트랜잭션이 해당 데이터의 수정,삭제 연산을 하지 못하게 막는 격리수준, 후행 트랜잭션에서 선행 트랜잭션의 SELECT 조건에 일치하는 데이터를 추가할 시 유령 데이터가 생겨 Phantom Read가 발생할 수 있음)

  • SERIALIZABLE : 가장 엄격한 격리수준, 트랜잭션의 동시성이 떨어져 성능에 치명적일 수 있음 (Reapeatable_Read와 다르게 Insert도 막는 기법이다. 즉, Phantom Read를 막을 수 있음)

-> 격리 수준이 높을수록 성능은 떨어짐

 

 

참고자료


https://feco.tistory.com/45

https://joont92.github.io/db/%ED%8A%B8%EB%9E%9C%EC%9E%AD%EC%85%98-%EA%B2%A9%EB%A6%AC-%EC%88%98%EC%A4%80-isolation-level/