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이 동작하는 것을 확인 할 수 있었다.