트랜잭션 전파에 대해 간단하게 정리해보려 합니다.
상세 설명은 다른 블로그를 같이 참조해 주세요.
트랜잭션의 전파에 대해 알아보기 전에 우선 스프링의 트랜잭션에 대해 간단하게 정리해 보겠습니다.
@Transaction?
@Transaction은 스프링의 AOP를 이용하여 개발자가 편하게 DB 관련 작업을 할 수 있도록 도와줍니다.
JPA, Mybatis 등을 사용하지 않을 때, 만약 Datasource를 이용해서 개발할 경우 getConnection(), close()를 하나하나 처리해주어야 합니다.
대략 아래와 같은 모습이겠죠.
public class QueryExam {
private static final String QUERY = "select count(*) from ANIMAL";
private DataSource dataSource;
public QueryExam(DataSource dataSource) {
this.dataSource = dataSource;
}
public void query() {
Connection conn = null;
try {
conn = dataSource.getConnection();
try (Statement stmt = conn.createStatement(QUERY);
ResultSet rs = stmt.executeQuery()) {
rs.next();
return rs.getInt(1);
}
} catch (SQLException e) {
throw new RuntimeException(e);
} finally {
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
}
}
}
}
}
벌써 보기만 해도 복잡한 코드가 나왔습니다.
위 코드를 보면 getConnection(), close() 같은 로직은 모든 DB 접근 로직에서 공통으로 처리해야 하는 부분입니다.
그래서 스프링에서는 이 부분을 AOP를 이용하여 간단하게 개발 가능하도록 해주고 있습니다.
@Transaction을 이용해서요.
그리고 DB의 기본 개념인 ACID를 지원(?) 해 줍니다. (위키 링크)
- Atomicity(원자성) : 각 트랜잭션이 성공/실패하는 단일 단위로 처리되도록 보장한다.
- Consistency(일관성) : 모든 데이터는 규칙에 맞는 일관성을 보장한다. (제약조건, 트리거 등의 모든 규칙에 유효해야 한다)
- Isolation(고립성) : 트랜잭션은 다은 트랜잭션의 영향을 받지 않는다.
- Durability(지속성) : 트랜잭션이 성공하면 그 결과는 영구적으로 저장된다.
트랜잭션 전파(propagation)
트랜잭션 전파는 어떤 트랜잭션이 동작중인 과정에서 다른 트랜잭션을 실행할 경우 '어떻게 처리하는가'에 대한 개념입니다.
아래 간단한 코드를 만들어 봤습니다.
public class Service1 {
private Service2 service2;
@Transaction
public void workAnything1() {
service2.workAnything2();
}
}
public class Service2 {
@Transaction
public void workAnything2() {
doAnything();
}
}
workAnything1(), workAnything2() 모두 @Transaction을 선언했습니다.
만약 Service1#workAnything()을 실행한다면 Service2#workAnything2()의 트랜잭션은 어떻게 될까요?
이 부분에 대해 처리해주는 것이 트랜잭션 전파입니다.
그리고 이 전파는 @Transaction의 propagation 속성을 통해 설정하게 됩니다.
value | desc |
REQUIRED | 기본값, tx을 항상 필요로 한다. 진행중인 tx이 있으면 해당 tx을 사용, 없다면 새로운 tx을 생 |
MANDATORY | tx를 필요로 한다. 진행중인 tx가 없을경우 exception을 발생 시킨다. |
REQUIRES_NEW | 항상 새로운 tx를 생성 한다. 진행중인 tx가 있다면 중지하고 새로운 tx를 시작한다. 새로운 tx가 종료되면 기존의 tx가 다시 동작 한다. |
SUPPORTS | tx를 필요로 하지 않는다. 만약 진행중인 tx가 있다면 사용한다. |
NOT_SUPPORTS | tx를 필요로 하지 않는다. 진행중인 tx가 있다면 중지하고 메서드가 종료된 후에 중지했던 tx를 다시 시작한다. |
NEVER | tx를 필요로 하지 않는다. 진행중인 tx가 있다면 exception을 발생 시킨다. |
NESTED | 진행중인 tx가 있다면 기존 tx에 중첩된 tx에서 메서드를 실행한다. |
Isolation
propagation에 대해 정리한 김에 @Transaction의 isolation 속성에 대한 설정에 대해서도 정리해 보겠습니다.
value | desc |
DEFAULT | 기본 설정값 사용. |
READ_UNCOMMITTED | 다른 tx가 commit하지 않은 데이터를 읽을 수 있다. |
READ_COMMITTED | 다른 tx가 commit한 데이터를 읽을 수 있다 |
REPEATABLE_READ | 처음 읽은 데이터와 두번째 읽은 데이터가 동일한 값을 같는다. |
SERIALIZABLE | 동일한 데이터에 대해 2개 이상의 tx가 동시에 수행될 수 없다. |
참조
위키 ACID : en.wikipedia.org/wiki/ACID
'Java & 스프링' 카테고리의 다른 글
Spring의 Jackson은 어떻게 동작할까? with ObjectMapper (0) | 2020.12.27 |
---|---|
[Spring] @Bean vs @Component 무엇이 다를까? (0) | 2020.12.25 |
[Spring] 스프링의 DI를 알아보자 (Dependency Injection) (0) | 2020.12.12 |
[Spring] auto DI, 생성자 주입 방식(Construct Injection) (0) | 2020.01.29 |
[spring] AOP를 이용하여 controller의 input data 자동 로그 기록하기 (0) | 2019.12.27 |
댓글