민스씨의 일취일장

LogT | Transaction Commit Rollback에 대해 알게된 모든 내용과 고민들 본문

Database

LogT | Transaction Commit Rollback에 대해 알게된 모든 내용과 고민들

읻민스 2023. 1. 25. 22:29
반응형

Transaction, Commit, Rollback에 대해 알게된 모든 내용과 고민들을 시간순으로 기록하는 페이지이다.


2023년 1월 25일

Transaction

  • 관습적 줄임말로 Tx을 자주 사용한다.
  • 데이터를 주고 받을 때 더이상 나눌 수 없는 하나의 최소 작업 단위이다.
  • INSERT, UPDATE, SELECT는 하나의 Tx를 구성한다.

예시

계좌이체가 트랜스액션의 가장 직관적이고 실질적인 예이다. 계좌이체는 원계좌로 부터의 "출금"과 목적 계좌로의 "입금"이라는 두 단계로 이루어져 있다. 출금만 이루어 지거나 입금만 이루워지는 경우를 계좌이체라고 부르지 않는다. 따라서 이 출금과 입금을 합한 계좌이체를 하나의 트랜스액션이라고 부를 수 있다. 또 둘 중 어느것 하나 제대로 이루어 지지 않으면 트랜스액션이 성립되지 않는다. 이를 가리켜 "all or nothing" 또는 "모 아니면 도"라고 부르기도 한다.

Commit & Rollback

커밋(Commit)과 롤백(Rollback)은 따로 보면 비효율적인 개념들이다.

커밋 commit

커밋은 데이터베이스에 작업한 내용을 실제로 적용하는 적용(저장)하는 것을 일컫는다. 다시 말해서 가공한 데이터는 커밋이라는 단계를 거쳐야 데이터베이스에 적용이된다.

롤백 rollback

롤백은 가공하던 데이터를 이전 상태로 되돌리는 것을 말한다. 하지만 단순히 실행취소와 롤백이 다른 점은 실행취소는 지금 당장 한 수정을 취소하는 반면 롤백은 가장 마지막에 커밋한 상태로 되돌리는 것을 말한다. 좀 더 정확한 이해를 위해 설명을 덧붙이자면, 롤백은 가장 마지막으로 커밋한 상태로 되돌리는 것이다. 다시 말해 커밋한 이후에 데이터를 잘못 가공한 것을 인식했을 때는 롤백을 해도 잘못 커밋한 상태로 밖에 돌아갈 수가 없다.


2023년 2월 2일

Transaction Manager

여러 메서드로 이루어진 코드를 하나의 Transaction으로 묶기 위해서는 TransactionManager를 활용해서 코드를 감싸줘야 한다.

@Autowired
DataSource ds;

// DataSource를 담은 Transaction Manager 객체를 생성한다.
PlatformTransactionManager tm = new DataSourceTransactionManager(ds);

// Transaction Manger를 이용해 Transaction Status 객체에 Tx 정보를 담아준다.
TransactionStatus status = tm.getTransaction(new DefaultTransactionDefinition());

// try catch 문을 활용해 Tx로 묶을 메서드들을 try문에 담아준 뒤 성공하면 commit, 실패하면 rollback 실행한다.
try {
	// n개의 메서드가 성공적으로 작동하면 커밋한다.
	method1;
    method2;
    .
    .
    .
    methodn;
    tm.commit(status);
} catch (Exception ex) {
	tm.rollback(status);
    throw ex;
} finally {
}

Bean으로 등록 후 간단히 @Transactional  애너테이션을 활용할 수도 있다.

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
	<property name="dataSource" ref="dataSource"/>
</bean>
<tx:annotaion-driven/>

Annotaion을 적용하면 위의 코드가 아래와 같이 간단해진다.

@Transactional
public void txMethod() throw Exception {
	mtehod1();
    method2();
    .
    . 
    methodn();
}

* @Transactional 애너테이션은 메서드 뿐만 아니라 클래스, 인터페이스에도 적용가능하다.

DataSourceUtils를 이용한 커넥션

DataSource 객체를 활용한 연결은 매번 독립적인 연설을 생성한다. 하지만 Transaction으로 관리되는 메서드들은 모두 하나의 연결(Connection)을 사용해야 한다. 때문에 Connection을 얻을 때 DataSource객체가 아닌 DataSourceTuils를 이용하는 변화가 필요하다.

// 기존 연결 방식
@Autowired
DataSource ds;

public txMethod() throws Exception{
	Connection conn = ds.getConnection();
    ...
}

// Transaction 적용릉 위한 연결 방식
@Autowired
DataSource ds;
public txMethod() throws Exception{
	Connection conn = DataSourceUtils.getConnection(ds);
}

@Transactional 사용

Bean으로 transactionManager를 등록한 후에는 @Transactional을 사용할 수 있다.

@Autowired
DataSource ds;

@Autowired
DataSourceTransactionManager tm;
// tm 객체를 만듦으로써 이전에 Tx를 위해 설정했던 걸 한번에 대체할 수 있다.

@Transactional
public void methodTx() throws Exception {
	method();
    // Tx의 try-catch 문에서 tx내의 내용만 작성하면 된다. 
    // commit() 메서드도 자동으로 실행되기 때문에 작성할 필요 없다.
}

@Transactional의 속성들

propagaion

Tx의 경계 (boundary)를 설정한다.

REQUIRED 진행중인 Tx의 요소로 구성된다.  
REQUIRES_NEW 별도의 Tx를 시작시키고 자신이 Rollback되어도 메인 Tx는 Commit된다.  
NESTED commit : Requires_new와 동일
자신 rollback : Requires_new와 동일
main-rollback : 자신도 rollback 된다.
 
MANDATORY 진행중인 Tx내에서만 작동하는 Tx가 된다.  
SUPPORTS 진행중인 Tx가 있다 REQUIRED 와 같고, 없으면 Tx 없이 코드만 진행한다.  
NOT_SUPPORTED Tx 적용하지 않는다. Tx가 진행중이면 일시 중지 시켜 버린다. (suspend)  
NEVER Tx 적용하지 않는다. Tx가 진행중이면 예외를 발생시켜버린다.  
728x90
반응형