readOnly 구분에 따른 커넥션 선택
jdbc:mysql:replication 스키마도 그렇고 아래에서 설명한 다중DB 커넥션 설정도 그렇고 현재 트랜잭션의 readOnly 값에 따라 master, slave DB가 선택된다.
https://findmypiece.tistory.com/255?category=968583
write 작업을 하는 커넥션의 경우 readOnly 값을 기본값인 false 로 지정해서 사용할텐데 대부분 트랜잭션에는 단순히 CUD 쿼리 뿐만 아니라 Read 쿼리도 포함되어 있다.
그렇다면 트래픽을 완전하게 분리하기 위해서 readOnly=false 로 지정된 트랜잭션의 쿼리 중 Read 쿼리는 readOnly=true 로 지정해서 slave DB에서 수행되게 해야 할까?
Spring에서 제공하는 트랜잭션 전파 규칙을 이용하면 이런 처리가 가능하다. 예를 들어 Service 단에 @Transactional 이 지정되어 있다면 Dao 단의 select 쿼리를 수행하는 메소드에 @Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = true) 를 추가로 지정하면 된다.
이렇게 되면 readOnly=false 인 트랜잭션에 포함된 작업 중 select 쿼리는 slave DB에서 새로운 커넥션을 얻어서 수행되게 할 수 있다.
그런데 이 작업은 하지 않느니만 못하다. 1개의 master 커넥션만으로 처리할 수 있는 작업을 여러개의 커넥션을 이용하게 되기 때문이다. 트래픽이 몰리면 안그래도 커넥션 고갈이 발생할텐데 굳이 이렇게 커넥션을 낭비할 필요는 없다.
일반적으로 JPA를 사용하는 Spring 환경이라면 Service 단 클래스에 @Transactional 을 지정하고 순수하게 Read 작업만 포함된 메소드에만 @Transactional(readOnly = true) 를 명시하도록 한다.
클래스에 @Transactional 를 지정할 경우 기본적으로 해당 클래스에 포함된 모든 메소드에 트랜잭션이 적용되는데 메소드에 다시 @Transactional(readOnly = true) 와 같이 트랜잭션을 지정할 경우 최종적으로 메소드에 지정된 트랜잭션 설정이 적용된다.