트랜잭션의 필요성

NoSQL과 빅데이터가 급부상하면서 RDBMS가 제공하는 엄격한 트랜잭션보다는 대용량 데이터 처리를 위한 느슨한 방식의 무결성 처리 기법을 적용하는 곳이 증가하고 있습니다.
하지만, 그럼에도 불구하고 전통적인 RDBMS가 제공하는 트랜잭션은 중요합니다.
예를 들어, 결제와 영화예매하는 시스템이 있습니다.
만약 이 시스템에서 결제는 이루어진 상태에서 영화 예매에 실패하는 상황이 발생하면 당연히 결제에 성공하면 안됩니다.
이런 경우 결제와 영화예매 모두 실패로 처리되어야 합니다.

 

트랜잭션이란?

트랜잭선은 여러 과정을 하나의 동작으로 묶을 때 사용됩니다.
트랜잭선 범위 내에 있는 처리 과정 중 한 가지라도 실패할 경우 전체 과정을 취소시킴으로써 데이터의 무결성을 보장합니다.
이러한 트랜잭션의 무결성 특징을 ACID라고 말합니다.
트랜잭션 과정 중 하나라도 실패한다면 모든 과정은 롤백됩니다.

 

롤백

데이터베이스에서 업데이트에 오류가 발생할 때, 이전 상태로 되돌리는 것을 말합니다.

 

ACID란 무엇일까요?

원자성(Atomicity)
트랜잭션은 한 개 이상의 동작을 논리적으로 한 개의 작업 단위로 묶습니다.
원자성은 트랜잭션 범위에 있는 동작이 모두 실행되거나 모두 실행되지 않음을 보장합니다.
모든 동작이 성공적으로 실행되면 트랜잭션은 성공입니다.
하나라도 실패한다면 트랜잭션은 실패하고 모든 과정은 롤백합니다.

 

일관성(Consistency)
트랜잭션은 항상 일괄적인 DB상태를 유지해야 합니다.
정의된 조건과 다른 결과가 나온다면 일관성이 지켜졌다고 말할 수 없습니다.
일관성이 지켜지지 않았다면 트랜잭션은 실패한 것이고, 모든 과정은 롤백합니다.

 

고립성(Isolation)
트랜잭션은다른 트랜잭션과 독립적으로 실행되어야 하며, 다른 트랜잭션이 동일한 데이터에 동시에 접근할 경우 접근을 제어해야 합니다.

 

지속성(Durability)
트랜잭션이 완료되면, 그 결과는 지속적으로 유지되어야 합니다.
DB에 반영된 데이터가 불특정하게 변경된다면, 지속성이 지켜졌다고 말할 수 없습니다.
이 경우에도 트랜잭션은 실패한 것이고, 모든 과정은 롤백합니다.

 

스프링의 트랜잭션 지원

스프링은 코드 기반의 트랜잭션 처리(Programmatic Transaction) 뿐 아니라 선언적 트랜잭션(Declarative Transaction)을 지원하고 있습니다.
개발자가 직접적으로 트랜잭션의 범위를 코드 수준에서 정의하고 싶은 경우에는 스프링이 제공하는 트랜잭션 템플릿 클래스를 이용해서 트랜잭션 범위를 지정할 수 있습니다.
또한, 설정 파일이나 어노테이션을 이용하여 트랜잭션 범위 및 규칙을 정의할 수 있기 때문에 트랜잭션을 매우 쉽게 관리할 수 있습니다.

 

트랜잭션 전파와 관련해서 스프링이 지원하는 속성

REQUIRED

메서드를 수행하는 데 트랜잭션이 필요하다는 것을 의미합니다.
현재 진행 중인 트랜잭션이 존재하면, 해당 트랜잭션을 사용합니다.
존재하지 않는다면 새로운 트랜잭션을 생성합니다.

 

MANDATORY

메서드를 수행하는 데 트랜잭션이 필요하다는 것을 의미합니다.
하지만, REQUIRED와 달리, 진행 중인 트랜잭션이 존재하지 않을 경우 익셉션을 발생시킵니다.

 

REQUIRES_NEW

항상 새로운 트랜잭션을 시작합니다.
기존 트랜잭션이 존재하면 기존 트랜잭션을 일시 중지하고 새로운 트랜잭션을 시작합니다.
새로 시작된 트랜잭션이 종료된 뒤에 기존 트랜잭션이 계속됩니다.

 

SUPPORTS

메서드가 트랜잭션을 필요로 하지 않지만, 기존 트랜잭션이 존재할 경우 트랜잭션을 사용한다는 것을 의미합니다.
진행 중인 트랜잭션이 존재하지 않더라도 메서드는 정상적으로 동작합니다.

 

NOT_SUPPORTED

메서드가 트랜잭션을 필요로 하지 않음을 의미합니다.
SUPPORTS와 달리 진행 중인 트랜잭션이 존재할 경우 메서드가 실행되는 동안 트랜잭션은 일시 중지되며, 메서드 실행이 종료된 후에 트랜잭션을 계속 진행합니다.

 

NEVER

메서드가 트랜잭션을 필요로 하지 않으며, 만약 진행 중인 트랜잭션이 존재하면 익셉션을 발생시킵니다.

 

NESTED

기존 트랜잭션이 존재하면, 기존 트랜잭션에 중첩된 트랜잭션에서 메서드를 실행합니다.
기존 트랜잭션이 존재하지 않으면 REQUIRED와 동일하게 동작합니다.
이 기능은 JDBC 3.0 드라이버를 사용할 때에만 적용됩니다.

 

트랜잭션 격리 레벨

DEFAULT

기본 설정을 사용합니다.

 

READ_UNCOMMITTED

다른 트랜잭션에서 커밋하지 않은 데이터를 읽을 수 있습니다.

 

READ_COMMITTED

다른 트랜잭션에 의해 커밋된 데이터를 읽을 수 있습니다.

 

REPEATABLE_READ

처음에 읽어 온 데이터와 두 번째 읽어 온 데이터가 동일한 값을 갖습니다.

 

SERIALIZABLE

동일한 데이터에 대해서 동시에 두 개 이상의 트랜잭션이 수행될 수 없습니다.

 

후기

스프링의 트랜잭션은 개념 뿐 아니라 내부적으로 어떻게 돌아가는지 공부할 필요가 있습니다.

 

참조 자료: 웹 개발자를 위한 Spring 4.0 프로그래밍

+ Recent posts