두 개의 작업들이 하나의 그룹처럼 묶여서 처리되는 중에 둘 중 하나라도 처리에 실패할 경우 애플리케이션의 신뢰성이 깨지는 상황이 발생하는 경우가 있다.
트랜잭션은 여러개의 작업들을 하나의 그룹으로 묶어서 처리하는 처리 단위인데, 이처럼 애플리케이션의 신뢰성이 깨지는 상황이 발생하면 트랜잭션이라고 부를 수 없다.
물리적으로는 여러 개의 작업이지만 논리적으로는 마치 하나의 작업으로 인식해서 전부 성공하든가 전부 실패하든가(All or Nothing)의 둘 중 하나로만 처리되어야 트랜잭션의 의미를 가진다.
이러한 트랜잭션 처리 방식은 애플리케이션에서 사용하는 데이터의 무결성을 보장하는 핵심적인 역할을 한다.
원자성(Atomicity)
트랜잭션에서의 원자성이란 작업을 더이상 쪼갤 수 없음을 의미한다.
예시로, 커피 주문 작업과 스탬프 횟수를 증가시키는 두 작업은 어떤 작업은 처리해도 되고, 어떤 작업은 처리하지 않아도 되는 식으로 쪼개서 처리할 수 없다.
따라서 논리적으로 하나의 작업으로 인식해서 둘 다 성공하든가 둘 다 실패하든가(All or Nothing) 중에서 하나로만 처리되는 것이 보장되어야 한다.
일관성(Consistency)
일관성은 트랜잭션이 에러없이 성공적으로 종료될 경우, 비즈니스 로직에서 의도하는대로 일관성있게 저장되거나 변경되는 것을 의미한다.
위 예시처럼, 주문한 커피의 수 만큼, 스탬프 횟수가 증가한다는 비즈니스 로직에 맞게 저장되거나 변경되어야 한다.
즉, 회원이 3잔의 커피를 주문했으면 스탬프 횟수가 3 증가한 값으로 저장이 되어있을거라고 예상했는데, 3이 아닌 숫자로 증가한 값이 조회 된다면 일관성에 위배 되는 것이다.
격리성(Isolation)
격리성은 여러 개의 트랜잭션이 실행될 경우 각각 독립적으로 실행이 되어야 함을 의미한다.
예를 들어 우리가 컴퓨터에서 워드 작업을 하고 있고, 동시에 뮤직 플레이어로 음악을 듣고 있다면 우리 눈에는 보이지 않지만 CPU는 위 두 가지 프로세스를 아주 빠른 속도로 번갈아가면서 실행을 시키는 것이다.
이처럼 데이터베이스 역시 성능 향상을 목적으로 한 개 이상의 트랜잭션을 번갈아가면서 처리할 수 있는데, 이 경우 각 트랜잭션이 다른 트랜잭션에 영향을 주지 않고 독립적으로 실행이 되어야 한다는 것이 바로 격리성(Isolation)이다.
지속성(Durability)
트랜잭션이 완료되면 그 결과는 지속되어야 한다는 의미다.
즉, 지속성은 데이터베이스가 종료되어도 데이터는 물리적인 저장소에 저장되어 지속적으로 유지되어야 한다는 의미다.
커밋(commit)
커밋(commit)은 모든 작업을 최종적으로 데이터베이스에 반영하는 명령어로써 commit 명령을 수행하면 변경된 내용이 데이터베이스에 영구적으로 저장된다.
만약 commit 명령을 수행하지 않으면 작업의 결과가 데이터베이스에 최종적으로 반영되지 않는다.
commit 명령을 수행하면, 하나의 트랜잭션 과정은 종료된다.
@Configuration
public class JpaBasicConfig {
private EntityManager em;
private EntityTransaction tx;
@Bean
public CommandLineRunner testJpaBasicRunner(EntityManagerFactory emFactory) {
this.em = emFactory.createEntityManager();
// (1)
this.tx = em.getTransaction();
return args -> {
tx.begin();
Member member = new Member("hgd@gmail.com");
em.persist(member);
tx.commit(); // (2)
};
}
}
(1) 에서 EntityManager 객체를 통해 Transaction 객체를 얻은 후에 (2) 에서 commit()
메서드를 호출해서 변경 사항을 최종적으로 반영할 수 있다.
롤백(rollback)
작업 중 문제가 발생했을 때, 트랜잭션 내에서 수행된 작업들을 취소한다.
따라서 트랜잭션 시작 이전의 상태로 되돌아간다.