Java/Spring

@Transactional 적용 안된 현상 정리

코딩공부 2022. 4. 9. 18:49

한 serviceImpl 안에서 insert로직이 2번 이루어 질때 하나의 로직이 실패 할시에 Transaction으로 rollback을 할 계획 이었다. 하지만 전에 진행하던 프로젝트와 똑같은 방법으로 진행하였지만 rollback이 안되고 exception이 일어나기 전까지의 로직이 수행되어서 DB에 저장되었는데 그 과정을 처리했던 방법 정리

 

구글링을 통해서 

1. Checked Exception일 경우

2. 한 클래스 내 @Transaction이 설정되어있지 않은 메소드에서 @Transaction이 설정된 메소드를 호출할 경우

3. 메소드가 private일 경우

4. @Transactional을 선언한 함수 내부에 try-catch구문

 

크게 4가지를 찾아보고 대입해 보았지만 해당 문제와 무관하였다. 

 

 

해결방법

 

사용하는 DB는 MariaDB를 사용하여서 진행하였는데 

Mysql, MariaDB가 자주 사용하는 스토리지 엔진은 MyISAM, InnoDB 이며, 단 DB 서버에서 테이블 등의 특정 오브젝트 단위로 여러 개의 스토리지 엔진을 사용 할 수 있다.

 

문제는 이 엔진에 있었다. 

 

MyISAM

  • 예전에는 기본 스토리지 엔진이었다. (현재는 InnoDB가 기본 스토리지 엔진이다)
  • 트랜잭션을 지원하지 않고, Table level locking을 사용한다.
  • 일반적으로 Oracle DB의 시퀀스(sequence)를 대체하기 위한 테이블을 만들 때 사용한다.

InnoDB

  • 트랜잭션을 지원한다.
  • Oracle DBMS에 익숙한 사용자가 가장 편하게 사용할 수 있는 스토리지 엔진이다.
  • MVCC(multi version concurrency control)를 지원하여 lock을 사용하지 않고 일관된 읽기 작업을 통해 고도의 동시성을 높일 수 있다.
  • Foreign key을 지원하고 Row level locking을 한다.
  • Primary Key를 기준으로 Clustering되어서 저장된다. 즉, PK를 기준으로 순서대로 디스크에 저장되는 구조로 PK에 의한 Range Scan이 빠르다.
  • MySQL에서는 InnoDB 스토리지 엔진을 사용하지만, MariaDB에서는 Percona사의 XtraDB 스토리지 엔진을 Built-in 하여 InnoDB로 명명한다. (큰 차이는 없다)

 

테이블을 만들때 엔진을 MyISAM으로 만들었던것을 확인 할 수 있었다. 

InnoDB로 엔진을 변경하니 기존과 같이 @Transactional이 동작하는 것을 확인 할 수 있었다.