끄적끄적

[JAVA] @Transaction 전파 및 격리에 대한 정리 본문

Back-end/Java

[JAVA] @Transaction 전파 및 격리에 대한 정리

mashko 2022. 4. 28. 18:03
반응형

@Transactional이란
@Transactional 을 사용 하여 데이터베이스 트랜잭션에서 메서드를 래핑할 수 있습니다.
이를 통해 트랜잭션에 대한 전파, 격리, 시간 초과, 읽기 전용 및 롤백 조건을 설정할 수 있습니다. 트랜잭션 관리자를 지정할 수도 있습니다 .

트랜잭션 구현 세부정보
Spring은 트랜잭션의 생성, 커밋 및 롤백을 관리하기 위해 프록시를 생성하거나 클래스 바이트 코드를 조작합니다. 프록시의 경우 Spring은 내부 메소드 호출에서 @Transactional 을 무시합니다.
간단히 말해서, callMethod 와 같은 메소드가 있고 이를 @Transactional 로 표시하면 Spring은 호출된 @Transactional 메소드 호출 주위에 일부 트랜잭션 관리 코드를 래핑합니다.

MANDATORY
현재 트랜잭션을 지원하고 존재하지 않는 경우 예외를 던집니다.
@Transactional(propagation = Propagation.MANDATORY)
NESTED
현재 트랜잭션이 있는 경우 중첩된 트랜잭션 내에서 실행하고 REQUIRED그렇지 않은 경우와 같이 동작합니다.
@Transactional(propagation = Propagation.NESTED)
NEVER
비트랜잭션으로 실행하고 트랜잭션이 있으면 예외를 던집니다.
@Transactional(propagation = Propagation.NEVER)
NOT_SUPPORTED
비트랜잭션으로 실행하고 현재 트랜잭션이 있으면 일시 중단합니다.
@Transactional(propagation = Propagation.NOT_SUPPORTED)
REQUIRED
현재 트랜잭션을 지원하고 존재하지 않는 경우 새 트랜잭션을 만듭니다.
@Transactional(propagation = Propagation.REQUIRED)
REQUIRED_NEW
새 트랜잭션을 만들고 현재 트랜잭션이 있으면 일시 중단합니다.
@Transactional(propagation = Propagation.REQUIRED_NEW)
SUPPORTS
현재 트랜잭션을 지원하고 트랜잭션이 없으면 트랜잭션 없이 실행합니다.
@Transactional(propagation = Propagation.SUPPORTS)

트랜잭션 격리

동시성 부작용

  • Dirty read: 동시 트랜잭션의 커밋되지 않은 변경 내용을 읽 습니다.
  • Nonrepeatable read : 동시 트랜잭션이 동일한 행을 업데이트하고 커밋하는 경우 행을 다시 읽을 때 다른 값을 얻 습니다.
  • Phantom read: 다른 트랜잭션이 범위의 일부 행을 추가하거나 제거하고 커밋하는 경우 범위 쿼리를 다시 실행한 후 다른 행을 가져옵니다.
READ_UNCOMMITTED
READ_UNCOMMITTED 는 가장 낮은 격리 수준이며 가장 동시 액세스를 허용합니다.
세 가지 동시성 부작용이 모두 발생합니다. 이 격리를 사용하는 트랜잭션은 다른 동시 트랜잭션의 커밋되지 않은 데이터를 읽습니다. 또한 반복 불가능한 읽기와 팬텀 읽기가 모두 발생할 수 있습니다. 따라서 행을 다시 읽거나 범위 쿼리를 다시 실행할 때 다른 결과를 얻을 수 있습니다.

@Transactional(isolation = Isolation.READ_UNCOMMITTED)
READ_COMMITTED
두 번째 격리 수준인 READ_COMMITTED Dirty read를 방지합니다.
나머지 동시성 부작용은 여전히 ​​발생할 수 있습니다. 따라서 동시 트랜잭션에서 커밋되지 않은 변경 사항은 우리에게 영향을 미치지 않지만 트랜잭션이 변경 사항을 커밋하면 다시 쿼리하여 결과가 변경될 수 있습니다.

@Transactional(Isolation= Isolation.READ_COMMITTED)
REPEATABLE_READ
REPEATABLE_READ Nonrepeatable read를 방지합니다. 따라서 동시 트랜잭션의 커밋되지 않은 변경 사항에 영향을 받지 않습니다.
또한 행에 대해 다시 쿼리할 때 다른 결과를 얻지 못합니다. 그러나 범위 쿼리를 다시 실행할 때 새로 추가되거나 제거된 행을 얻을 수 있습니다.
또한 업데이트 손실을 방지하기 위해 필요한 가장 낮은 수준입니다. 두 개 이상의 동시 트랜잭션이 동일한 행을 읽고 업데이트할 때 업데이트 손실이 발생합니다. REPEATABLE_READ 는 행에 대한 동시 액세스를 전혀 허용하지 않습니다. 따라서 손실된 업데이트가 발생할 수 없습니다.
@Transactional(isolation = Isolation.REPEATABLE_READ)
SERIALIZABLE
SERIALIZABLE 은 가장 높은 격리 수준입니다. 언급된 모든 동시성 부작용을 방지하지만 동시 호출을 순차적으로 실행하기 때문에 동시 액세스 비율이 가장 낮을 수 있습니다.
즉, 직렬화 가능한 트랜잭션 그룹의 동시 실행은 직렬로 실행하는 것과 동일한 결과를 가집니다.
@Transactional(isolation = Isolation.SERIALIZABLE)

DEFAULT
기본 격리 수준은 DEFAULT 입니다. 결과적으로 Spring이 새 트랜잭션을 생성할 때 격리 수준은 RDBMS의 기본 격리가 됩니다. 따라서 데이터베이스를 변경할 경우 주의해야 합니다.

우리는 또한 다른 격리를 가진 일련의 메소드를 호출하는 경우를 고려해야 합니다 . 정상적인 흐름에서 격리는 새 트랜잭션이 생성될 때만 적용됩니다. 따라서 어떤 이유로 메서드가 다른 격리에서 실행되는 것을 허용하지 않으려면 TransactionManager::setValidateExistingTransaction 을 true로 설정해야 합니다.
REPEATABLE_READ 는 MySQL의 기본 수준입니다. Oracle은 REPEATABLE_READ 를 지원하지 않습니다 .

 

반응형
Comments