스프링에서 Transaction을 어떻게 관리하고 작동하는 지 알아보려고 합니다
트랜잭션의 종류가 꼭 DB에만 속한건 아니지만 여기서 말하는 트랜잭션은 DB 트랜잭션을 말할 예정입니다.
만약 데이터베이스의 데이터를 추가 또는 변경하는 도중에 예외가 발생한다면 DB의 데이터들은 작업이 일어나기 전의 상태로 돌아가게 되고(Rollback)
정상적인 데이터 처리를 진행하였으면 작업 결과를 적용하는(Commit) 이것이 트랜잭션의 개념 입니다.
위의 특징들은 트랜잭션의 가장 기본적인 개념이자 진짜 중요한 개념입니다.
진~~~짜 중요해요 두번 강조합니다.
스프링에서는 크게 2가지 방식으로 트랜잭션을 관리할 수 있는 방법을 제공합니다.
스프링에서 데이터 관리 방법들은 JdbcTemplate, JPA 등 여러가지가 존재하는데 해당 기술마다 트랜잭션을 사용하는 방법도 달라집니다.
Spring에서는 PlatformTransactionManager 인터페이스를 이용한 트랜잭션 관리를 제공합니다.
해당 인터페이스는 총 3가지 기능을 가지고 있는데 밑에와 같습니다.
TransactionStatus
를 return따라서 PlatformTransactionManager
를 명시적으로 사용해 저희가 원하는 트랜잭션을 구성하여 관리할 수 있습니다. (직접 AOP 만들어 트랜잭션 관리를 해준다던지 등등)
TransactionStatus
트랜잭션 실행를 제어하고 상태를 조회하는 방법을 제공
최종적으로 제공하는 메소드는 밑에와 같습니다.
// TransactionStatus 기능
boolean isNewTransaction();
boolean hasSavepoint();
void setRollbackOnly();
boolean isRollbackOnly();
void flush();
boolean isCompleted();
참고로 JpaTransactionManager
으로 JPA, Mybatis 둘다 하나의 트랜잭션에서 같이 관리할 수 있습니다!!
그 이유는 JpaTransactionManager
가 DataSource 접근이 가능하여 일반적인 JDBC를 사용 가능하기 때문입니다.
이때 Mybatis SqlSession에 트랜잭션을 위임하는게 아닌 Spring Transaction에 위임합니다.
@Transactional
어노테이션을 사용하게되면 AOP를 통한 트랜잭션 관리가 위와 같이 진행하게 됩니다.
AOP를 통한 트랜잭션 관리가 되어 저희는 어노테이션만 붙이면 되는 편한 방식입니다.
아마 대부분의 사람들이 해당 방식으로 트랜잭션을 관리하지 않을까 싶네요.
실질적인 트랜잭션 관리 로직은 PlatformTransactionManager
사용하는 것처럼 똑같이 작동하게 됩니다.
단 테스트 환경일 시에는 @Transactional
이 성공, 실패와 상관없이 롤백한다는 점 기억하면 될 것같습니다. (아무런 옵션 없이 사용했을 때)
여러 트랜잭션이 동시에 처리될 때 특정 트랜잭션이 다른 트랜잭션에서 변경하거나 조회하는 데이터들을 볼 수 있게 허용할지 말지를 결정하는 것 (DB Lock 이랑 살짝 비슷한 느낌이네요)
REQUIRED
REQUIRES_NEW
NESTED
SUPPORTS
Mandatory
Not Supported
Never
동시 트랜잭션에 의해 적용된 변경 사항이 서로에게 표시되는 방식을 설명합니다.
동시 트랜잭션은 여러 사용자가 동시에 실행할 수 있는 트랜잭션입니다.
격리 수준은 트랜잭션에서 0개 이상의 동시성 부작용을 방지합니다.
DB에 따른 격리 수준을 지원하고 안할 수 있으니 사용하는 DB가 어떠한 격리 수준을 지원하는지 확인 바랍니다.
Default
Read Uncommitted (Isolation.READ_UNCOMMITTED
)
Read Committed (Isolation.READ_COMMITTED
)
Repeatable Read (Isolation.REPEATABLE_READ
)
Isolation.SERIALIZABLE
)학생 때 개발 했을 때 기본적인 어노테이션만 사용해서 에러시 롤백 사용하는 정도였는데
실무에서 개발을 해보니까 트랜잭션이 너무나도 중요하다는걸 느끼는 중이여서 재밌네요
@Transactional
방식이 아닌 PlatformTransactionManager
로 직접 트랜잭션 관리를 하는 도중이라서 이러한 이해가 필요하였습니다.
특히나 동시성 문제로 인해 격리 수준 설정은 가장 많이 마주치고 복잡한 문제 중 하나인데 어떻게 해결해야 할지 생각을 많이 하게 되네요
트랜잭션 격리 수준을 설정을 해서 해결해도 되고 아니면 DB Lock을 걸어 해결해도 되고~~
트랜잭션에 대해서 좀더 깊은 이해를 한 것 같아서 재밌습니다~~!