programing

스프링 @트랜잭션 읽기 전용 전파

lastmemo 2023. 3. 12. 10:21
반응형

스프링 @트랜잭션 읽기 전용 전파

명령 패턴을 사용하여 웹 계층이 단일 트랜잭션의 컨텍스트 내에서 휴지 상태 엔티티와 함께 작동하도록 하는 실험을 하고 있습니다(따라서 느린 로딩 예외를 피할 수 있습니다).하지만 지금은 어떻게 거래해야 할지 혼란스럽습니다.

는 내 서비스 합니다.이 메서드는 내 로 주석이 있습니다.@Transactional 메서드의 읽기 전용입니다).@Transactional(readOnly = true). -읽기/쓰기 -읽기/쓰기가 되다.

서비스 계층은 웹 계층을 대신하여 전달된 명령을 실행하는 명령어핸들러를 표시합니다.

@Transactional
public Command handle(Command cmd) throws CommandException

의 「」를 것이라고 합니다.handle메서드 트랜잭션입니다.이치노명령어를 구현하여 여러 서비스 레이어 메서드에 콜을 발신하는 경우 명령어핸들러는 명령어 내에서 호출된 조작이 읽기 전용인지 읽기/쓰기인지 두 가지 조작의 조합인지를 알 수 없습니다.

이 예에서는 전파가 어떻게 기능하는지 이해할 수 없습니다. the the the the the 를 만든다면handle() 법 methodreadOnly = true가 " " "로 주석이 @Transactional(realOnly = false)

우선 봄은 지속성을 유지하지 않기 때문에 선 속 체 지 할 은 무 수 없 first, of 그, allence what spring,때명 specify since doesn에않 itself시'readOnly정확히 말해 봐.히 해 this 이 속성은 공급자에게 힌트만 힌트입니다.이 속성은 공급자에 대한 힌트에 불과하며 동작은 휴지 상태에 따라 달라집니다.

If you specify 지정한 경우readOnly as ~하듯이true플래시 모드는 현재 휴지 상태 세션과 동일하게 설정되어 세션이 트랜잭션을 커밋할 수 없게 됩니다.

또한 JDBC Connection에서 setReadOnly(true)가 호출됩니다.이것은 기본 데이터베이스에 대한 힌트이기도 합니다.데이터베이스가 이를 지원하는 경우(대부분 지원), 기본적으로 다음과 같은 효과가 있습니다.FlushMode.NEVER도 없기

이제 트랜잭션 전파의 구조를 살펴보겠습니다.

를 으로 설정하지 .readOnly로로 합니다.true읽기/쓰기 트랜잭션이 발생합니다.예: '알겠습니다').REQUIRES_NEW어떤 시점에서 트랜잭션이 중단되어 새로운 트랜잭션이 시작되고 최종적으로 커밋된 후 첫 번째 트랜잭션이 재개될 수 있습니다.

,,, 의의다다 다다다.이 일어나는지 readOnly이 시나리오에 포함시킵니다.

읽기/쓰기 트랜잭션의 메서드가 readOnly 트랜잭션을 필요로 하는 메서드를 호출하는 경우 첫 번째 메서드를 일시 중단해야 합니다. 그렇지 않으면 두 번째 메서드의 마지막에 플러시/커밋이 발생하기 때문입니다.

반대로 읽기/쓰기가 필요readOnly 트랜잭션 내에서 메서드를 호출하면 첫 번째 메서드는 플러시/커밋할 수 없기 때문에 첫 번째 메서드는 일시 중단되고 두 번째 메서드는 이 메서드가 필요합니다.

read Only-to-read Only 및 read/write-to-read/write 케이스에서는 외부 트랜잭션을 일시 중단할 필요가 없습니다(명백히 전파를 지정하지 않는 한).

이전 트랜잭션이 계속되므로 readOnly=true에서 readOnly=false를 호출할 수 없습니다.

이 예에서는 서비스 레이어의 handle() 메서드가 새로운 읽기/쓰기 트랜잭션을 시작하고 있습니다.핸들 메서드가 주석을 단 서비스 메서드를 차례로 호출하는 경우 읽기 전용은 기존 읽기/쓰기 트랜잭션에 대신 참여하므로 적용되지 않습니다.

이러한 메서드가 읽기 전용이어야 하는 경우 전파를 사용하여 주석을 달 수 있습니다.NEQUES_NEW는 기존 읽기/쓰기 트랜잭션에 참여하지 않고 새로운 읽기 전용 트랜잭션을 시작합니다.

다음으로 작업 예를 나타냅니다.CircuitStateRepository는 스프링 데이터 JPA 저장소입니다.

BeanS는 transactional=read-only Bean1을 호출하여 검색을 수행하고 transactional=read-write Bean2를 호출하여 새 개체를 저장합니다.

  • Bean1은 읽기 전용 tx를 시작합니다.

31 09:39:44.199 [pool-1-thread-1]디버깅 os.orm.jpa.JpaTransactionManager - [nz.co.snaphone.wcim.business]라는 이름으로 새 트랜잭션을 만듭니다.Bean 1. start Something ] :PRAGATION_REQUIRED, Isolation_DEFAULT, readOnly; "

  • 빈2가 포함되어 있습니다.

    31 09:39:44.230 [pool-1-thread-1]디버깅 os.orm.jpa.JpaTransactionManager - 기존 트랜잭션 참여

    데이터베이스에 커밋된 것은 없습니다.

Bean2를 바꿉니다.@Transactional propagation=Propagation.REQUIRES_NEW

  • Bean1은 읽기 전용 tx를 시작합니다.

    31 09:31:36.418 [pool-1-thread-1]디버깅 os.orm.jpa.JpaTransactionManager - [nz.co.snaphone.wcim.business]라는 이름으로 새 트랜잭션을 만듭니다.Bean 1. start Something ] :PRAGATION_REQUIRED, Isolation_DEFAULT, readOnly; "

  • Bean2가 새로운 읽기/쓰기 tx를 시작합니다.

    31 09:31:36.449 [pool-1-thread-1]디버깅 os.orm.jpa.JpaTransactionManager - 현재 트랜잭션을 일시 중단하고 [nz.co.syslogafone.wcim.business]라는 이름으로 새 트랜잭션을 만듭니다.Bean 2. create Something ]

그리고 Bean2에 의해 이루어진 변경은 이제 데이터베이스에 커밋됩니다.

다음은 스프링 데이터, 휴지 상태 및 오라클을 사용하여 테스트한 예입니다.

@Named
public class BeanS {    
    @Inject
    Bean1 bean1;

    @Scheduled(fixedRate = 20000)
    public void runSomething() {
        bean1.startSomething();
    }
}

@Named
@Transactional(readOnly = true)
public class Bean1 {    
    Logger log = LoggerFactory.getLogger(Bean1.class);

    @Inject
    private CircuitStateRepository csr;

    @Inject
    private Bean2 bean2;

    public void startSomething() {    
        Iterable<CircuitState> s = csr.findAll();
        CircuitState c = s.iterator().next();
        log.info("GOT CIRCUIT {}", c.getCircuitId());
        bean2.createSomething(c.getCircuitId());    
    }
}

@Named
@Transactional(readOnly = false)
public class Bean2 {    
    @Inject
    CircuitStateRepository csr;

    public void createSomething(String circuitId) {
        CircuitState c = new CircuitState(circuitId + "-New-" + new DateTime().toString("hhmmss"), new DateTime());

        csr.save(c);
     }
}

디폴트로는 트랜잭션 전파는 REQUIRED 입니다.즉, 같은 트랜잭션이 트랜잭션 발신자에서 트랜잭션 착신자로 전파됩니다.이 경우 읽기 전용 상태도 전파됩니다.예를 들어 읽기 전용 트랜잭션이 읽기-쓰기 트랜잭션을 호출하는 경우 전체 트랜잭션은 읽기 전용이 됩니다.

느린 로드를 허용하기 위해 Open Session in View 패턴을 사용할 수 있습니까?이렇게 하면 핸들 방식이 트랜잭션 방식일 필요가 전혀 없습니다.

현재 활성 트랜잭션의 설정을 무시하고 새 트랜잭션에만 설정을 적용합니다.

org.springframework.transaction.Platform Transaction ManagerTransaction Status get Transaction(트랜잭션 정의)트랜잭션을 슬로우하다예외.지정된 전파 동작에 따라 현재 활성 트랜잭션을 반환하거나 새 트랜잭션을 만듭니다.
분리 수준이나 시간 초과 등의 매개 변수는 새 트랜잭션에만 적용되므로 활성 트랜잭션에 참여할 때 무시됩니다.
또한 모든 트랜잭션 정의 설정이 모든 트랜잭션 관리자에 의해 지원되는 것은 아닙니다.트랜잭션 관리자를 적절하게 구현하면 지원되지 않는 설정이 발생할 때 예외가 발생합니다.
상기 규칙의 예외는 읽기 전용 플래그입니다.명시적인 읽기 전용 모드가 지원되지 않는 경우 이 플래그는 무시해야 합니다.기본적으로 읽기 전용 플래그는 잠재적인 최적화를 위한 힌트일 뿐입니다.

언급URL : https://stackoverflow.com/questions/1614139/spring-transactional-read-only-propagation

반응형