✔ 참고영상
🚩 [10분 테코톡] 🐤 샐리의 트랜잭션
🚩 데이터베이스 트랜잭션(transaction)을 아십니까?
예를 들어 은행 입출금 시스템을 생각해보자.
- 출금자가 만원을 이체한다고 할 때, 출금자의 계좌에 만원 이상의 금액이 있는지 확인
- 만원 이상이 있다는 것을 확인한 후 입금자에게 송금
- 출금자의 잔액은 만원 감소하며 입금자의 잔액은 만원 증가
이 일련의 업무는 분리되어서 안되며 일부만 실행되어서도 안된다. 이렇게 절대로 깨져서는 안되는 하나의 작업을 트랜잭션이라고 한다.
모든 데이터베이스는 자체적으로 트랜잭션을 지원하는데, 이는 하나의 명령을 실행했을 때 데이터베이스가 온전히 그 명령을 실행해주는 것을 의미한다. 데이터 베이스는 기본적으로 트랜잭션을 관리하기 위한 설정을 가지고 있다.
(1) 트랜잭션 성공 (J가 H에게 20만원을 송금하는 경우)
mysql> START TRANSACTION;
mysql> UPDATE account SET balance=balance-200000 WHERE id='J';
mysql> UPDATE account SET balance=balance+200000 WHERE id='H';
mysql> COMMIT
(2) 트랜잭션 실패 (J가 H에게 30만원 송금하려다 중간에 오류가 발생한 경우)
mysql> START TRANSACTION;
mysql> UPDATE account SET balance=balance-300000 WHERE id='J';
// 오류 발생
mysql> ROLLBACK;
✍ AUTOCOMMIT
: 각각의 SQL문을 자동으로 transction 처리해주는 개념. SQL문이 성공적으로 실행되면 자동으로 commit하고 실행 중에 문제가 발생하면 자동으로 rollback해준다. MySQL에서는 default로 autocommit 기능이 enabled 되어있는데,
SATRT TRANSACTION실행 시에는 자동으로 off된다. 이후 트랜잭션이 종료되면 원래 autocommit상태로 돌아간다.
데이터베이스에서는 각각의 명령을 하나의 트랜잭션으로 보고 보장하기 때문에 여러 명령을 하나의 트랜잭션으로 묶고 싶은 경우 개발자가 직접 트랜잭션의 경계설정을 통해 트랜잭션을 명시하는 작업이 필요하다.
Spring은 트랜잭션 경계 설정을 데이터베이스에 전달해주는 기능이 있는데, 트랜잭션 추상화 인터페이스인 PlatformTransactionManager를 제공한다.
public interface PlatformTransactionManager
extends TransactionManager {
TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException
void commit(TransactionStatus status)
void rollback(TransactionStatus status)
}
스프링이 제공하는 TransactionManager 구현체는 대표적으로 DataSourceTransactionManager, JpaTransactionManager, JtaTransactionManager 등이 있다.
이렇게 직접적으로 코드에 구현하는 방식 외에도 AOP를 이용한 선언적 트랜잭션을 제공하는데, 대표적인 예는 아래와 같다.
(1) TX Namespace
: Bean 설정파일에서 트랜잭션 매니저를 등록하고 속성과 대상을 정의해 트랜잭션을 적용하겠다고 명시하는 것. 코드에는 영향을 주지 않고 일괄적으로 트랜잭션을 적용하고 변경할 수 있다는 장점이 있다.
(2) 어노테이션 @Transactional
일반적으로 가장 많이 사용하는 방식. 트랜잭션 어노테이션은 메서드, 클래스, 인터페이스 등에 적용할 수 있다. 클래스 상단에 적용된 어노테이션에 대해서는 해당 클래스에 존재하는 모든 메서드에 어노테이션이 적용된다. 세밀한 설정을 할 수 있다는 장점이 있다.
트랜잭션은 네 가지 성질(ACID)를 바탕으로 신뢰를 보장한다.
❗ 기억하기
- 트랜잭션을 어떻게 정의해서 쓸 지는 개발자가 정하는 것이다.
⇒ 구현하려는 기능과 ACID 속성을 제대로 이해해야 트랜잭션을 잘 정의할 수 있다.
- DBMS가 모든 ACID를 보장해주지는 않는다.
⇒ Defalut 설정이 있긴 하지만 모든 것을 알아서 처리해주는 것은 아니기 때문에 상황에 따라서는 개발자가 따로 설정해야 하는 부분이 있다.