스프링의 트랜잭션
기능
- 트랜잭션 추상화
- 서비스의 종류나 환경이 변화되더라도 트랜잭션을 사용하는 코드는 그대로 유지 가능
- 트랜잭션 동기화
트랜잭션 경계설정방법
- PlatformTransactionManager의 구현체들을 사용
- getTransaction -> commit or rollback 메서드 사용
- 코드를 이용한 트랜잭션 경계설정
- 선언적 트랜잭션 경계설정: 데코레이터를 이용한 트랜잭션 프록시 빈 사용
@Transactional 동작방법
프록시 기반으로 다이나믹 프록시나 CGLib를 통해서 구현되거나, 타깃 오브젝트를 직접 조작하는 방식의 AspectJ방식이 있습니다. 스프링 boot는 디폴트로 CGLib를 사용
- 다이나믹 프록시는 인터페이스에 적용하는 프록시이기 때문에 인터페이스가 필요
- CGLib는 클래스를 상속해서 프록시를 만들기 때문에 final 클래스는 불가
- AspectJ는 프록시를 타깃 오브젝트 앞에 두지 않고, 타깃 오브젝트 자체를 직접 조작
http://wonwoo.ml/index.php/post/1708
트랜잭션 속성
트랜잭션 전파
새로운 트랜잭션이 시작될 경우, 이것을 기존의 트랜잭션에 참여시키는 방법을 결정
- required: 디폴트. 기존의 트랜잭션이 있으면 참여하고 없으면 새로 시작
- requires_new: 매번 새로운 트랜잭션
- nested: 부모의 트랜잭션에 참여하지만, 자신이 에러가 발생할 경우에는 부모에 영향을 끼치지 않는다. 로그작업같은데 쓰임. 내부적으로 savepoint를 사용
트랜잭션 격리수준
- read_uncommitted: dirty read(트랜잭션 작업이 완료되지 않았는데도 다른 트랜잭션에서 볼 수 있는 현상) 발생. 다른 트랜잭션의 커밋하지 않은 데이터들을 읽을 수 있음
- read_committed: 다른 트랜잭션의 커밋한 데이터를 읽을 수 있음. 다시 읽었을 때 데이터가 달라질 수 있는 문제 발생
- repeatable_read: 하나의 트랜잭션이 일관적인 데이터를 볼 수 있도록 함. 단, 다른 트랜잭션에서의 삽입의 경우에는 새로운 데이터가 추가될 수 있음.
- serializable: 읽기에는 shared_lock, 쓰기에는 exclusive_lock을 걸어서 극도의 일관성을 보장.
그 외
- timeout
- read_only
- rollback_for