본문 바로가기
Spring/ETC

@Transactional 에 대해

by YoonJong 2023. 8. 15.
728x90

@Transaction

 

 

스프링 프레임워크를 사용하면 보통 서비스 레이어(비즈니스로직) 에 @Transactional 어노테이션을 선언해 트랜잭션을 시작한다.

해당 어노테이션에 있으면, 메서드를 호출하기 직전에 스프링의 AOP 가 먼저 동작한다.

  1. 메서드가 시작하기 전 트랜잭션을 시작한다.
  2. 메서드가 정상적으로 종료되면 트랜잭션을 커밋하면서 종료한다.

트랜잭션을 커밋할 때, 플러시 하면서 DB에 저장하고 커밋한다.

만약, 예외가 발생하면 트랜잭션을 롤백하고 종료한다 ( 커밋은 발생 X ) 

+ 기본적으로 Unchecked Exception, Error 만을 롤백한다.

 

 

트랜잭션이란?

  1. 데이터베이스의 상태를 변경하는 작업 또는 한번에 수행되어야 하는 연산
  2. Begin , commit 을 자동으로 수행
  3. 예외 발생 시, rollback을 자동으로 수행
  4. 트랜잭션의 특징

 

처리방법  

  • 스프링에서는 선언적 어노테이션을 사용한다 -> @Transactional
    ( XML 을 이용해서 설정할 수 있는데 지양한다. )
  • 적용된 범위 내에서 프록시 객체가 생성되어 commit or rollback 을 진행한다.

 

 

트랜잭션의 옵션 종류

 

Propagation 의 옵션

https://devlog-wjdrbs96.tistory.com/424

 

 

— 사용시 주의할 점 

  1. 우선순위를 가지고 있다.
  2. Public 에서만 적용가능

 

 

— 트랜잭션의 격리 수준

https://velog.io/@guswns3371/데이터베이스-트랜잭션-격리수준

밑으로 갈수록 트랜잭션끼리 고립성은 높아지고 성능은 떨어진다.
일관성을 지키기 위해 ( 동시성 문제 ) 를 해결하기 위한 옵션

  1. READ UNCOMMITED : 다른 트랜잭션에서 커밋되지 않는 내용도 참조 가능 
  2. READ COMMITED : 다른 트랜잭션에서 커밋된 내용만 참조 가능 ( 기본값 )
  3. REPETABLE READ : 트랜잭션에 진입하기 이전에 커밋된 내용만 참조 가능
  4. SERIALIZABLE : 트랜잭션에 진입하면 락을 걸어 다른 트랜잭션이 접근하지 못하도록 ( 성능 최하 )

 

생길 수 있는 현상

  1. Dirty Read : 수정중인 데이터 이며, 아직 Commit 되지 않은 값을 읽고, 롤백을 하면 다시 이전의 값을 읽어 일관성이 맞지 않는다.
  2. Non-Repeatable Read : 한 트랜잭션에서 쿼리를 두번 수행했을 때, 다른 트랜잭션이 값을 수정 또는 삭제해서 같은 쿼리의 결과가 다른 값이 발생하는 현상
  3. Phantom Read : insert 에서만 발생하는문제, 첫 번째에 없던 쿼리의 결과가 두 번째 쿼리에서 나타나는 현상 

 

데이터에 여러 커넥션들이 수정요청을 한다.

커넥션1 이 접근할때는 락을 걸어버리면 다른 커넥션은 접근 불가.

커넥션1 이 락을 풀면 다른 커넥션이 접근 가능.

 

** 트랜잭션의 격리 수준을 어떻게 처리할지에 대한 방법 중 하나가 락 이다

 

락 => 동시성 제어 

  • 동시에 발생하는 수정 요청에 대한 데이터 일관성을 지키기 위한 메커니즘

 

트랜잭션 격리 수준

  • 여러 트랜잭션에 대해 각 트랜잭션들을 어떻게 처리할지에 대한 전략 

트랜잭션 => 원자성 보장 ( 성공 혹은 실패 )

 

낙관점 잠금  / 비관적 잠금 

  • 요청이 많은 서버에서 여러 트랜잭션이 동시에 같은 데이터에 업데이트를 발생 시킬 경우, 일부 요청이 유실되는 장애가 발생할 수 있다.
    동시 읽기/업데이트 간에 데이터가 일관성 있도록 유지해야 한다.

 

  1. 낙관적 잠금 ( 애플리케이션 Lock )
    - 트랜잭션을 필요로 하지않는다 -> 롤백을 수동으로 구현
    - 데이터 갱신 시, 충돌이 발생하지 않을 것이라고 낙관적으로 보고 잠금을 거는 것
    - DB에 락을 걸기보다 충돌 방지에 가깝다
    - 동시에 동일한 데이터에 대한 여러 업데이트가 간섭하지 않도록 version 이라는 속성을 확인해서 엔티티의 변경사항을 감지한다
    - version 과 같은 별도의 컬럼을 추가한다.
    - @Version 을 이용 ( 사용하면 + 1 되며, version 이 변경되어 충돌을 막는다 )
  2. 비관적 잠금 ( 데이터 베이스 트랜잭션 Lock )
    - 트랜잭션을 사용하며, 롤백이 자동으로 진행
    - 처음부터 충돌이 발생할 것이라고 예상
    - 데이터베이스에 접근할 때부터 락을 걸어버린다.

 

참고 : 

우르의 Lock & JPA Lock

https://sabarada.tistory.com/175 - 낙관적, 비관적 락 비교 

728x90

댓글