Transactional이란?
데이터베이스의 상태를 변경하고자 할 때, 한 번에 수행되어야 하는 연산들을 의미합니다.
트랜잭션을 만들고, begin, commit까지 완료하면 하나의 트랜잭션이 수행된다라고 말합니다.
@Transactional 어노테이션은 트랜잭션을 선언하고 begin, commit까지 자동으로 수행해줍니다. 당연히 예외 발생 시 rollback처리도 자동을 수행해주죠. 트랜잭션은 4가지의 성질을 가지고 있습니다. (트랜잭션 ACID 성질이라고도 합니다.)
- 원자성(Atomicity) : 트랜잭션은 아토믹해야합니다. 한 트랜잭션 내에서 실행한 작업들은 하나의 단위로 처리해서 모두 성공, 모두 실패가 되어야 합니다. 때문에 rollback 처리가 필수인 것 입니다.
- 일관성(Consistency) : 트랜잭션은 일관성 있는 데이터베이스 상태를 유지해야 합니다. 연산이 실행될 수 있는 환경들이 조건으로 주어지고, 이를 반드시 만족시켜야 합니다.
- 격리성(Isolation) : 동시에 실행되는 트랜잭션들이 서로 영향을 미치지 않도록 해야 합니다.
- 영속성(Durability) : 성공적으로 완료(commit) 된 트랜잭션은 데이터베이스에 영구적으로 보존되어야 합니다. 완료 후에 컴퓨터가 꺼진다면 데이터는 이미 저장되었으므로 보존되고, 완료 전에 컴퓨터가 꺼진다면 데이터는 원자성 원칙을 따라, 트랜잭션 수행하기 전으로 돌아갑니다.
네트워크 환경에서 ACID특성을 보장하는 것은 굉장히 어렵습니다. 연결이 끊길 수도 있고 두 사용자가 동시에 DB의 동일한 부분을 접근할 수도 있습니다. 트랜잭션의 commit 여부를 각 사용자로부터 확인하기 위해 2단계 commit이 분산 트랜잭션에 적용됩니다.
정리해보면, 스프링에서는 간단하게 어노테이션 방식으로 @Transactional을 메소드, 클래스, 인터페이스 위에 추가하여 사용하는 방식이 일반적입니다. 이 방식을 선언적 트랜잭션이라 부르며, 적용된 범위에서는 트랜잭션 기능이 포함된 프록시 객체가 생성되어 자동으로 commit 혹은 rollback을 진행해줍니다.
@Transactional(readOnly=true)가 꼭 필요한가?
결론은 써주는 게 좋다입니다.
- 첫 번째, 조회한 데이터를 return 한다고 해도 의도치 않게 데이터가 변경되는 일을 사전에 방지해줍니다.
- 두 번째, 해당 옵션인 경우 CUD 작업이 동작하지 않고, 스냅샷 저장, 변경 감지(dirty check)의 작업을 수행하지 않아 성능이 향상됩니다. 여기서 dirty checking은 상태 변경검사인데요, dirty란 상태의 변화가 생긴 정도라고 이해하면 될 것 같습니다.
JPA에서는 트랜잭션이 끝나는 시점에 변화가 있는 모든 엔티티 객체를 데이터베이스에 자동으로 반영해줍니다. JPA에서는 엔티티를 조회하면 해당 엔티티의 처음 조회 상태 그대로 스냅샷을 만들어놓습니다. 그리고 트랜잭션이 끝나는 시점에는 이 스냅샷과 비교해서 다른 점이 있다면 Update Query를 데이터베이스로 전달합니다. - 이동욱 님 블로그
- 세 번째, MySQL을 사용할 때 데이터가 날아가는 것을 방지하기 위해서 이중화 구성(master - Slave)을 하는 경우가 있는데 DB가 master와 slave로 나누어져 있다면 readOnly = true로 있는 경우에는 읽기 전용으로 master가 아닌 slave를 호출하게 됩니다. 즉, 상황에 따라 DB 서버의 부하를 줄이고 약간의 최적화를 할 수 있습니다.
- 마지막으로 @Transactional(readOnly=true) 어노테이션이 있다면 코드를 접하는 사람들이 직관적으로 보기에 해당 메서드는 READ에 대한 동작만 수행할 것이라고 예상합니다. 그리고 결과적으로도 읽기 동작만 수행이 되죠. 또한 이 어노테이션을 보고 누구나 한눈에 알아볼 수 있고, 신뢰성을 보장한다고 받아들입니다.
출처 : https://jojoldu.tistory.com/415
Reference :https://jojoldu.tistory.com/415
https://junhyunny.github.io/spring-boot/jpa/junit/transactional-readonly/