[Spring] Transaction

내용
transaction
AOP
진행일시
2021/03/22
속성

1. Transaction이란?

여러 과정을 하나의 행위로 묶을 때 사용된다.
여러 단계를 수행했을때, 하나라도 실패하면 모두 취소되어야 한다.
이렇게 함으로써 데이터의 무결성을 보장한다. 모두 반영하거나 반영하지 않음.

2.Transaction을 쓰는이유?

Transaction을 관리하기위해 쓰이며 Spring에서는 SqlSession으로 commit, rollback 이 불가 그래서 Transaction을 이용하여 commit과 rollback을 진행한다. TransactionStatus객체가 있으며 어떻게 트랜잭션할것건지 설정을 transactionManager을 이용한다. DefaultTransactionDefinition은 transaction설정정보를 담고있다.

3. 트랜잭션에 대한 설정 정보를 담고 있는 객체

DefaultTransactionDefinition def = new DefaultTransactionDefinition();
전파 행위옵션 * REQUIRED : 진행중인 트랜잭션이 있으면 현재 메서드를 그 트랜잭션에서 실행하되 그렇지 않은 경우 새 트랜잭션을 시작해서 실행한다. * * REQUIRED_NEW : 항상 새 트랜잭션을 시작해 메서드를 실행하고 진행중인 트랜잭션이 있으면 잠시 중단시킨다. * * SUPPORTS : 진행중인 트랜잭션이 있으면 현재 메서드를 그 트랜잭션 내에서 실행하되, 그렇지 않을 경우 트랜잭션 없이 실행한다. * * NOT_SUPPORTED : 트랜잭션 없이 현재 메서드를 실행하고 진행중인 트렌잭션이 있으면 잠시 중단한다. * * MANDATORY : 반드시 트랜잭션을 걸고 현재 메서드를 진행중인 트랜잭션이 없으면 예외를 던진다. * * NEVER : 반드시 트랜잭션없이 현재 메서드를 실행하되 진행 중인 트랜잭션이 있으면 예외를 던진다. * * NESTED : 진행중인 트랜잭션이 있으면 현재 메서드를 이 트랜잭션의 중첩트랜잭션 내에서 실행한다. 진행중인 트랜잭션이 없으면 새 트랜잭션을 실행한다. * 배치 실행 도중 처리해야할 업무가 백만개라고 하면 10만개씩 끊어서 커밋하는 경우 * 중간에 자못되어도 중첩 트랜잭션을 롤백하면 전체가아닌 10만개만 롤백된다. * (세이브포인트를 이용하는 방식이다. 따라서 세이브 포인트를 지원하지 않는 경우 사용이 불가능하다.) * */ def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); 격리 레벨 ( 동시성 고려 ) * DEFAULT: DB의 기본 격리 수준을 사용한다. 대다수는 READ_COMMITTED가 기본 격리 수준이다. * * READ_UNCOMMITTED : 다른 트랜젝션이 아직 커밋하지 않은 값을 또 다른 트랜잭션이 읽을 수 있다. * 따라서 오염된 값을 읽거나, 재현 불가능한 읽기, 허상읽기 등의 문제가 발생할수 있다. * * READ_COMMITED : 트랜잭션이 다른 트랜잭션에서 커밋한 값만 읽을 수 있다. * 오염된 값 읽기 문제는 해결되지만 재현 불가능한 읽기 및 허상 읽기는 여전히 발생할 수 있다. * * REPEATABLE_READ : 트랜잭션이 어떤 필드를 여러번 읽어도 동일한 값을 읽도록 보장한다. * 트랜잭션이 지속되는 동안에는 다른 트랜젝션이 해당 필드를 변경할 수 없다 * 오염된 값읽기, 재현 불가능한 읽기문제는 해결되지만 허상읽기는 여전히 발생할 수 있다. * * SERIALIZABLE : 트랜잭션이 테이블을 여러번 읽어도 정확히 동일한 로우를 읽도록 보장한다. * 트랜잭션이 지속되는 동안에는 다른 트랜잭션이 해당 테이블에 삽입, 수정, 삭제를 할 수 없다. * 동시성 문제는 모두 해소되지만 성능은 현저하게 떨어진다. * * 오염된 값 : 하나의 트랜젝션이 데이터를 변경 후 잠시 기다리는 동안 다른 트랜젝션이 데잍를 읽게된다면 * 격리 레벨이 READ_UNCOMMITTED인 경우 아직 변경 후 커밋하지 않은 재고 값을 그대로 읽게 된다. * 그러나 처음 트랜젝션이 데이터를 롤백하게되면 다른 트렌젝션이 읽은 값은 더 이상 유효하지 않은 일시적인 값이 된다. * 이것을 오염된 값이라고 한다. * * 재현 불가능한 읽기 : 처음 트랜젝션이 데이터를 수정하면 수정이되고 아직 커밋되지 않은 로우에 수정 잠긍믈 걸어둔 상태이다. * 결국 다른 트랜잭션은 이 트랜젝션이 커밋 혹은롤백되고 수정 잠금이 풀릴 때 까지 기다렷다가 읽을 수 밖에 없게 된다. * 하지만 다른 로우에 대해서는 또 다른 트랜잭션이 데이터를 수정하고 커밋을 하게 되면 * 가장 처음에 동작한 트랜잭션이 데이터를 커밋하고 다시 조회를 한 경우 처음 읽은 그 값이 아니게 된다. * 이것이 재현 불가능한 읽기이다. * * 허상 읽기 : 처음 트랜잭션이 테이블에서 여러 로우를 읽은 후 이후 트랜젝션이 같은 테이블의 로우를 추가하는 경우 * 처음 트랜잭션이 같은 테이블을 다시 읽으면 자신이 처음 읽었을 때와 달리 새로 추가된 로우가 있을 것이다. * 이것을 허상읽기라고한다. (재현 불가능한 읽기와 유사하지만 허상읽기는 여러 로우가 추가된느 경우를 말한다.) * */ def.setIsolationLevel(DefaultTransactionDefinition.ISOLATION_SERIALIZABLE); /*트랜잭션에 대한 실행을 제어하거나 트랜잭션 상태 등을 조회할 수 있는 간단한 방법을 제공하는 객체*/ TransactionStatus status = transactionManager.getTransaction(def);
HTML
복사

4. Aop를 이용한 트랜잭션

AOP를 이용한 트랜잭션은 javaconfig방식과 xmlconfig방식이 있다

4-1 . javaconfig방식

xml쪽에 AOP와 transaction선언 해주기
트랜잭션을 선언해주면 class쪽에 어노테이션을 이용하여 트랜잭션을 사용할 수 있다.

4-2 xmlConfig방식

xml방식에서는 transaction과 AOP설정을 다해주는 방식이다.

5. readOnly 속성

트랜잭션을 읽기 전용으로 설정할 수 있다.-
성능을 최적화하기 위해 사용할 수도 있고 특정 트랜잭션 작업 안에서 쓰기 작업이 일어나는 것을 의도적으로 방지하기 위해 사용할 수도 있다.
일부 트랜잭션 매니저의 경우 읽기전용 속성을 무시하고 쓰기 작업을 허용할 수도 있기 때문에 주의해야 한다.-
일반적으로 읽기 전용 트랜잭션이 시작된 이후 INSERT, UPDATE, DELETE 같은 쓰기 작업이 진행되면 예외가 발생한다.
aop/tx 스키마로 트랜잭션 선언을 할 때는 이름 패턴을 이용해 읽기 전용 속성으로 만드는 경우가 많다. 보통 get이나 find 같은 이름의 메소드를 모두 읽기전용으로 만들어 사용하면 편리하다.
@Transactional 의 경우는 각 메소드에 일일이 읽기 전용 지정을 해줘야 한다.
read-only 애트리뷰트 또는 readOnly 앨리먼트로 지정한다.
true인 경우 insert, update, delete 실행 시 예외 발생, 기본 설정은 false
ex)@Transactional(readOnly = true)

6. 트랜잭션 롤백 예외(rollback-for, rollbackFor, rollbackForClassName)

선언적 트랜잭션에서는 런타임 예외가 발생하면 롤백한다.
반면에 예외가 전혀 발생하지 않거나 체크 예외가 발생하면 커밋한다.
체크 예외를 커밋 대상으로 삼은 이유는 체크 예외가 예외적인 상황에서 사용되기보다는 리턴 값을 대신해서 비즈니스적인 의미를 담은 결과를 돌려주는 용도로 많이 사용되기 때문이다.-
스프링에서는 데이터 액세스 기술의 예외는 런타임 예외로 전환돼서 던져지므로 런타임 예외만 롤백 대상으로 삼은 것이다.
하지만 기본 동작방식을 바꿀 수도 있다.
ex ) 체크 예외지만 롤백 대상으로 삼아야 하는 것이 있다면 XML의 rolback-for 애트리뷰트나 애노테이션의 rollbackFor 또는 rollbackForClassName 앨리먼트를 이용해서 예외를 지정하면 된다.
rollback-for 나 rollbackForClassName 은 예외 이름을 넣으면 되고, rollbackFor 는 예외 클래스를 직접 넣는다.
@Transactional 에서는 다음과 같이 클래스 이름 대신 클래스를 직접 사용해도 된다.
@Transactional(readOnly=true, rollbackFor=NoSuchMemberException.class)
rollbackFor 속성
특정 예외가 발생 시 강제로 Rollback
설정 예: @Transactional(rollbackFor=Exception.class)
noRollbackFor 속성
특정 예외의 발생 시 Rollback 처리되지 않음
설정 예: @Transactional(noRollbackFor=Exception.class)
[갓대희의 작은공간]

7. timeout속성

지정한 시간내에 해당 메소드 수행이 완료되지 않은 경우 rollback 수행 -1일 경우 no timeout(Default=-1)
ex)@Transactional(timeout=10)