트랜잭션 원자성
1. 개요
1. 개요
트랜잭션 원자성은 데이터베이스 시스템과 분산 컴퓨팅에서 트랜잭션이 갖추어야 할 핵심 속성 중 하나이다. 이 개념은 하나의 트랜잭션을 구성하는 모든 작업이 전부 성공하거나, 아니면 전혀 실행되지 않은 상태로 되돌아가야 함을 의미한다. "원자성"이라는 용어는 더 이상 쪼갤 수 없는 기본 단위인 원자에서 비롯되었으며, 트랜잭션도 마찬가지로 분할될 수 없는 하나의 논리적 단위로 취급되어야 한다는 점을 상징한다.
예를 들어, 은행 계좌 간 이체 작업은 출금과 입금이라는 두 개의 데이터 변경 작업으로 구성된다. 원자성이 보장되지 않는다면, 출금만 성공하고 입금은 실패하는 상황이 발생할 수 있어 데이터의 정합성이 심각하게 훼손된다. 원자성은 이러한 부분적 성공을 방지하여, 트랜잭션의 모든 연산이 완전히 적용되거나(커밋) 전혀 적용되지 않도록(롤백) 보장하는 역할을 한다.
이 속성은 ACID 트랜잭션 특성의 첫 글자를 차지하며, 나머지 일관성, 격리성, 지속성을 위한 기초를 제공한다. 원자성의 구현은 주로 로그 기반 복구, 락킹 메커니즘, 2단계 커밋과 같은 기술을 통해 이루어진다. 데이터의 신뢰성과 정확성이 요구되는 금융, 예약, 재고 관리 등 다양한 비즈니스 시스템에서 트랜잭션 원자성은 필수적인 개념으로 자리 잡고 있다.
2. 원자성의 정의와 중요성
2. 원자성의 정의와 중요성
트랜잭션 원자성은 데이터베이스 시스템에서 하나의 트랜잭션을 구성하는 모든 연산이 전부 성공하거나, 아니면 전혀 실행되지 않은 것처럼 모두 실패해야 함을 보장하는 속성이다. 이는 더 이상 분할할 수 없는 단위라는 원자(Atomic)의 개념에서 비롯된 용어이다. 예를 들어, 은행 계좌 이체 트랜잭션은 출금과 입금이라는 두 개의 연산으로 구성된다. 원자성은 이 두 연산이 모두 완료되거나(커밋), 하나라도 실패하면 이전 상태로 완전히 롤백되어야 함을 의미한다. 부분적으로만 실행된 상태(예: 출금만 되고 입금은 안 된 상태)는 허용되지 않는다.
원자성의 중요성은 데이터 무결성을 유지하는 데 있다. 시스템 장애, 네트워크 문제, 소프트웨어 오류 등 어떤 이유로든 트랜잭션이 중단될 경우, 원자성은 데이터가 불완전하거나 모순된 상태에 빠지지 않도록 보호한다. 이는 금융 거래, 재고 관리, 예약 시스템 등 정확성이 절대적으로 요구되는 비즈니스 로직의 핵심 기반이 된다. 원자성이 없다면 부분적 업데이트로 인해 데이터의 신뢰성이 크게 훼손될 수 있다.
원자성은 일반적으로 롤백 메커니즘을 통해 구현된다. 트랜잭션이 시작되면 시스템은 변경 전의 데이터 상태를 기록해둔다. 이후 트랜잭션 실행 중 오류가 발생하면 이 기록을 이용해 모든 변경 사항을 취소하고 트랜잭션 시작 전의 상태로 되돌린다. 성공적으로 완료될 경우에는 변경 사항을 확정(커밋)한다. 이렇게 함으로써 사용자나 응용 프로그램은 트랜잭션이 "전부 아니면 전무"의 방식으로 처리된다는 것을 신뢰할 수 있다.
3. 원자성의 구현 메커니즘
3. 원자성의 구현 메커니즘
트랜잭션 원자성을 구현하기 위한 주요 메커니즘에는 로그 기반 복구, 락킹 메커니즘, 2단계 커밋 등이 있다. 이러한 메커니즘들은 시스템 장애 발생 시에도 모든 작업이 적용되거나 전혀 적용되지 않도록 보장한다.
로그 기반 복구, 특히 WAL은 가장 널리 사용되는 방법이다. 이 메커니즘은 데이터베이스에 실제 변경을 적용하기 전에, 모든 변경 사항을 안정적인 저장 장치에 순차적으로 기록한 로그 파일에 먼저 기록한다. 트랜잭션이 커밋되면 로그에 커밋 기록을 남기고, 이후에 메모리나 디스크의 실제 데이터를 갱신한다. 시스템 장애가 발생하면 복구 관리자는 이 로그를 검사하여, 커밋 기록은 있지만 데이터 갱신이 완료되지 않은 트랜잭션은 재실행하고, 커밋 기록이 없는 트랜잭션은 변경 사항을 모두 취소한다.
락킹 메커니즘은 동시에 실행되는 여러 트랜잭션이 같은 데이터를 충돌 없이 접근하도록 관리하여 원자성의 실행을 돕는다. 트랜잭션은 데이터 항목을 읽거나 쓰기 전에 해당 항목에 대한 락을 획득해야 한다. 쓰기 락은 배타적이며, 트랜잭션이 완료될 때까지 다른 트랜잭션이 해당 데이터를 읽거나 쓸 수 없게 한다. 이를 통해 트랜잭션의 중간 상태가 다른 트랜잭션에 노출되는 것을 방지하고, 롤백 시 변경 사항을 확실히 되돌릴 수 있는 기반을 마련한다.
분산 데이터베이스나 마이크로서비스 환경에서는 2단계 커밋 프로토콜이 사용된다. 이 프로토콜은 여러 독립적인 시스템에 걸친 트랜잭션의 원자성을 보장한다. 프로토콜은 준비 단계와 커밋 단계로 구성된다. 조정자는 모든 참여자에게 트랜잭션 준비를 요청하고, 모든 참여자가 준비 완료를 보고하면 커밋을 지시한다. 만약 한 참여자라도 준비에 실패하면 조정자는 모든 참여자에게 중단을 지시한다. 이 과정을 통해 모든 노드가 일관되게 커밋하거나 중단하도록 강제한다.
메커니즘 | 주요 목적 | 적용 범위 |
|---|---|---|
로그 기반 복구 (WAL) | 장애 복구 및 원자성 보장 | 단일 데이터베이스 시스템 |
락킹 메커니즘 | 동시성 제어 및 원자적 실행 지원 | 단일/분산 시스템 내 동시 접근 |
2단계 커밋 (2PC) | 분산 트랜잭션의 원자성 보장 | 여러 독립적인 시스템(분산 DB, 서비스) |
3.1. 로그 기반 복구 (WAL)
3.1. 로그 기반 복구 (WAL)
로그 기반 복구, 특히 선행 기록 로그는 트랜잭션 원자성을 보장하는 핵심적인 구현 메커니즘 중 하나이다. 이 방법은 트랜잭션이 데이터베이스의 실제 페이지를 변경하기 전에, 모든 변경 내용을 안정적인 저장 장치(예: 디스크)에 로그 레코드 형태로 먼저 기록하는 것을 원칙으로 한다. 시스템은 커밋이 발생하기 전에 반드시 해당 트랜잭션의 모든 로그 레코드를 디스크에 강제로 기록하여, 시스템 장애가 발생하더라도 로그를 통해 작업을 재실행하거나 취소할 수 있는 근거를 마련한다.
WAL의 작동은 크게 재실행과 취소라는 두 가지 복구 작업을 중심으로 이루어진다. 재실행은 커밋된 트랜잭션의 변경 사항이 장애로 인해 데이터 파일에 완전히 반영되지 않았을 경우, 로그를 읽어 최종 상태로 복구하는 과정이다. 반대로 취소는 커밋되지 않은 트랜잭션이 데이터 파일에 부분적으로 기록되었을 경우, 로그를 역순으로 읽어 변경 사항을 원래 상태로 되돌리는 과정이다. 이를 통해 트랜잭션은 '모두 반영되거나 모두 반영되지 않거나'라는 원자성을 만족하게 된다.
WAL 메커니즘의 주요 구성 요소와 처리 흐름은 다음과 같이 요약할 수 있다.
구성 요소 / 단계 | 설명 |
|---|---|
로그 버퍼 | 트랜잭션에 의해 생성된 로그 레코드가 임시로 저장되는 메모리 영역이다. |
로그 레코드 기록 | 변경 내용(트랜잭션 ID, 변경 대상, 이전 값, 이후 값 등)이 로그 버퍼에 기록된다. |
로그 강제 기록 | 트랜잭션 커밋 시점에, 해당 트랜잭션의 모든 로그 레코드를 로그 버퍼에서 안정적인 로그 파일로 내린다. |
데이터 페이지 갱신 | 로그가 안전하게 기록된 후에야, 실제 데이터베이스 버퍼 풀의 데이터 페이지를 변경한다. |
체크포인트 | 주기적으로 모든 버퍼 풀의 변경된 데이터 페이지를 디스크에 동기화하고, 이를 로그에 표시하여 복구 시작 지점을 만든다. |
이 방식은 성능 면에서도 장점을 가진다. 데이터 페이지의 변경 사항을 매번 즉시 디스크에 쓰지 않고, 로그라는 순차적 파일에 먼저 기록함으로써 쓰기 작업의 부하를 줄일 수 있다. 또한, 체크포인트를 활용하면 복구 시 전체 로그가 아닌 최근 체크포인트 이후의 로그만 검사하면 되므로 복구 시간을 단축할 수 있다. 따라서 WAL은 원자성과 지속성을 효율적으로 보장하는 기반 기술로 널리 사용된다.
3.2. 락킹 메커니즘
3.2. 락킹 메커니즘
락킹 메커니즘은 데이터베이스 시스템에서 여러 트랜잭션이 동시에 같은 데이터에 접근할 때 발생할 수 있는 충돌을 방지하고 원자성을 보장하기 위한 핵심 기법이다. 이 메커니즘은 트랜잭션이 특정 데이터 항목을 사용하는 동안 다른 트랜잭션이 그 데이터를 동시에 수정하지 못하도록 잠금을 설정한다. 이를 통해 트랜잭션이 중간 상태의 데이터를 읽거나 쓰는 것을 방지하여, 모든 작업이 완전히 적용되거나 전혀 적용되지 않는 원자적 상태를 유지할 수 있다.
락의 종류는 주로 공유락과 배타락으로 구분된다. 공유락은 데이터를 읽기만 하는 트랜잭션이 사용하며, 여러 트랜잭션이 동시에 같은 데이터에 대한 공유락을 획득할 수 있다. 반면, 배타락은 데이터를 쓰거나 수정하는 트랜잭션이 필요로 하며, 한 데이터 항목에 대해 한 번에 하나의 트랜잭션만 배타락을 보유할 수 있다[1]. 락의 범위는 전체 데이터베이스, 테이블, 페이지, 행 등 다양한 수준으로 적용될 수 있으며, 이를 락의 세분성이라고 한다.
락 종류 | 목적 | 호환성 | 획득 가능 트랜잭션 수 |
|---|---|---|---|
공유락(S-Lock) | 데이터 읽기 | 공유락끼리 호환됨 | 여러 개 |
배타락(X-Lock) | 데이터 쓰기/수정 | 다른 모든 락과 비호환 | 한 개 |
락킹 메커니즘을 구현할 때는 데드락이 발생하지 않도록 주의해야 한다. 데드락은 두 개 이상의 트랜잭션이 서로가 보유한 락을 기다리며 무한정 대기하는 상태를 말한다. 이를 방지하기 위해 대기-다이 그래프를 사용하여 사이클을 탐지하거나, 트랜잭션 시작 시점에 필요한 모든 락을 미리 요청하는 방법 등이 사용된다. 또한, 락을 너무 오래 유지하면 시스템의 동시성과 성능이 저하될 수 있으므로, 트랜잭션 설계와 락 해제 시점을 신중히 결정해야 한다.
3.3. 2단계 커밋 (2PC)
3.3. 2단계 커밋 (2PC)
2단계 커밋(2PC)은 분산 데이터베이스 시스템이나 마이크로서비스 환경에서 여러 개의 독립적인 데이터베이스 또는 리소스에 걸친 하나의 트랜잭션 작업이 원자적으로 수행되도록 보장하는 분산 트랜잭션 커밋 프로토콜이다. 이 프로토콜은 하나의 트랜잭션이 여러 참여자(예: 다른 데이터베이스 서버)에 영향을 미칠 때, 모든 참여자가 작업을 커밋하거나 모두 롤백하도록 조정하는 역할을 한다.
프로토콜은 두 개의 결정적인 단계로 진행된다. 첫 번째 단계는 준비 단계로, 중앙 조정자인 트랜잭션 매니저가 모든 참여자에게 트랜잭션 커밋 준비를 요청한다. 각 참여자는 자신의 로컬 작업을 완료하고 모든 변경 사항을 영구 저장소에 기록한 후, 준비가 완료되면 '예' 표시를, 문제가 있으면 '아니오' 표시를 조정자에게 회신한다. 두 번째 단계는 커밋 단계로, 조정자가 모든 참여자로부터 '예' 응답을 받으면 최종 커밋 명령을 전송한다. 만약 하나라도 '아니오' 응답을 받거나 타임아웃이 발생하면, 조정자는 모든 참여자에게 롤백 명령을 보낸다.
2PC는 원자성을 보장하는 강력한 메커니즘을 제공하지만 몇 가지 명확한 단점을 가진다. 가장 큰 문제는 블로킹 현상이다. 한 참여자가 조정자로부터 준비 요청을 받고 '예'로 응답한 후, 조정자의 최종 결정(커밋 또는 롤백)을 기다리는 동안 해당 참여자의 리소스는 잠긴 상태로 유지된다. 만약 이 시점에 조정자가 고장 나면, 참여자들은 불확실한 상태에 빠져 무기한 대기하거나 수동 개입을 필요로 할 수 있다[2]. 또한, 모든 단계에서 네트워크 통신이 필요하므로 성능 오버헤드가 크고 지연 시간이 길어질 수 있다.
이러한 한계로 인해, 3단계 커밋(3PC) 같은 대안 프로토콜이나, 보상 트랜잭션 패턴을 사용하는 사가 패턴과 같은 최종적 일관성 모델이 분산 시스템에서 더 널리 채택되는 경향이 있다.
4. 원자성 보장의 한계와 트레이드오프
4. 원자성 보장의 한계와 트레이드오프
트랜잭션의 원자성을 완벽하게 보장하는 것은 시스템 설계에 있어 여러 가지 비용과 제약을 수반한다. 가장 두드러진 한계는 성능 오버헤드다. 원자성을 보장하기 위해 사용되는 락킹, 로그 기록, 2단계 커밋 등의 메커니즘은 추가적인 입출력 작업과 동시성 제어를 필요로 한다. 이는 특히 쓰기 작업이 빈번한 환경에서 처리량을 저하시키고 응답 시간을 증가시킬 수 있다. 또한, 장시간 트랜잭션이 자원을 점유하는 경우 다른 트랜잭션의 대기 시간이 길어져 시스템 전체의 처리율이 떨어질 수 있다.
분산 시스템 환경에서 원자성을 보장하는 것은 훨씬 더 복잡한 과제가 된다. 네트워크 분할, 노드 장애, 통신 지연과 같은 문제는 원자성 프로토콜의 실행을 방해한다. 예를 들어, 2단계 커밋 프로토콜은 모든 참여 노드가 준비 상태에 도달해야 커밋할 수 있으며, 단일 노드의 장애나 응답 지연이 전체 트랜잭션의 완료를 차단하는 블로킹 문제를 발생시킨다. 이러한 취약점을 해결하기 위해 3단계 커밋이나 Paxos 같은 합의 알고리즘이 제안되었지만, 이는 다시 프로토콜의 복잡성과 메시지 교환 오버헤드를 증가시킨다.
따라서 시스템 설계자는 애플리케이션의 요구사항에 따라 원자성 보장의 수준을 조정해야 하는 트레이드오프에 직면한다. 높은 일관성이 필수적인 금융 시스템에서는 성능 저하를 감수하고 강력한 원자성을 선택하는 반면, 대규모 웹 서비스나 분산 데이터베이스에서는 가용성과 확장성을 우선시하여 결과적 일관성과 같은 느슨한 모델을 채택하기도 한다. 이는 ACID 특성과 BASE 특성 사이의 근본적인 선택으로 귀결된다.
보장 수준 | 장점 | 단점 | 주요 사용 사례 |
|---|---|---|---|
강한 원자성 (ACID) | 데이터 정확성 최대화, 복구 용이 | 높은 성능 오버헤드, 확장성 제한 | |
약한/결과적 원자성 (BASE) | 높은 가용성, 확장성 우수 | 일시적 불일치 가능, 애플리케이션 로직 복잡 |
이러한 트레이드오프는 원자성이 무조건적인 선이 아니라, 데이터의 정확성, 시스템 성능, 개발 복잡도, 비용 간의 균형을 고려한 설계 결정의 결과임을 보여준다.
4.1. 성능 오버헤드
4.1. 성능 오버헤드
원자성 보장은 시스템에 필연적인 성능 오버헤드를 발생시킨다. 가장 대표적인 오버헤드는 로그 기반 복구를 위한 WAL 기록과, 동시성 제어를 위한 락킹 메커니즘에서 비롯된다. 모든 데이터 변경 전에 로그를 먼저 안정적인 저장소에 기록해야 하므로, 실제 데이터 변경 작업보다 최소 한 번 이상의 추가적인 디스크 I/O가 발생한다. 또한, 락을 획득하고 해제하는 과정에서의 관리 비용과, 락 경합으로 인한 대기 시간이 시스템의 전체 처리량을 제한한다.
이 오버헤드는 트랜잭션의 지속 시간과 직접적인 연관이 있다. 장시간 실행되는 트랜잤션은 리소스를 더 오랫동안 점유하게 되어, 다른 트랜잭션의 대기 시간을 증가시키고 시스템의 동시성을 저하시킨다. 특히 배치 작업이나 복잡한 분석 쿼리를 트랜잭션으로 처리할 경우 성능 저하가 두드러진다.
성능과 안정성 사이의 트레이드오프를 관리하기 위해 다양한 완화 기법이 사용된다. 격리성 수준을 낮추어 락의 범위나 지속 시간을 줄이거나, 낙관적 동시성 제어를 채택하는 방법이 있다. 또한, 모든 작업을 원자적으로 묶기보다는, 비즈니스 로직에 따라 컴펜세이팅 트랜잭션이나 사가 패턴과 같은 대안적 설계를 적용하여 성능을 최적화하기도 한다.
4.2. 분산 시스템에서의 복잡성
4.2. 분산 시스템에서의 복잡성
분산 시스템에서 트랜잭션 원자성을 보장하는 것은 단일 데이터베이스 환경에 비해 훨씬 복잡한 과제를 제시한다. 여러 지리적으로 분리된 노드나 서비스가 하나의 트랜잭션 작업에 참여할 때, 네트워크 지연, 부분적 실패, 시계 불일치 등의 문제가 발생할 수 있다. 이러한 환경에서 모든 참여자가 작업을 완료하거나, 아무도 작업을 완료하지 않는 원자적인 상태를 보장하는 것은 본질적으로 어렵다.
주요 난제 중 하나는 네트워크 분할과 같은 부분적 실패 상황에서의 결정 문제이다. 한 노드가 실패하거나 네트워크로부터 격리되었을 때, 다른 정상 노드들이 트랜잭션을 커밋할지 아니면 중단할지 일관되게 결정해야 한다. 이를 해결하기 위한 고전적인 프로토콜인 2단계 커밋은 모든 참여자의 동의를 얻어 커밋하거나, 한 명이라도 반대하면 전체를 롤백하는 방식을 사용한다. 그러나 이 방식은 코디네이터 노드의 단일 장애점 문제가 있으며, 장애 발생 시 참여자 노드들이 무기한 대기 상태에 빠질 수 있는 단점이 있다.
보다 복잡성을 완화하기 위해 등장한 프로토콜로는 3단계 커밋과 같은 변형이나, 분산 트랜잭션의 사용을 최소화하는 설계 패턴이 있다. 예를 들어, 사가 패턴은 하나의 분산 트랜잭션을 여러 개의 로컬 트랜잭션으로 분해하고, 각 로컬 트랜잭션이 완료되면 다음 트랜잭션을触发하는 방식으로 진행한다. 실패가 발생하면 보상 트랜잭션을 실행하여 원자성을 유사하게 보장한다[3]. 이러한 방식은 가용성과 성능을 높이는 대신, 애플리케이션 수준에서 복구 로직의 복잡성을 증가시키는 트레이드오프가 존재한다.
프로토콜/패턴 | 핵심 메커니즘 | 주요 장점 | 주요 단점 |
|---|---|---|---|
코디네이터가 참여자들의 준비/커밋 상태를 조정 | 강한 원자성 보장 | 성능 저하, 단일 장애점, 차단 문제 | |
로컬 트랜잭션의 체이닝과 보상 트랜잭션 | 가용성과 확장성 높음, 차단 없음 | 애플리케이션 로직 복잡, 최종 일관성만 제공 |
결론적으로, 분산 환경에서 완벽한 원자성을 보장하는 것은 CAP 정리[4]에 의해 본질적인 제약을 받는다. 따라서 시스템 요구사항에 따라 강한 원자성, 높은 가용성, 낮은 지연 시간 중에서 적절한 균형을 찾는 설계 결정이 필요하다.
5. 다른 트랜잭션 속성과의 관계
5. 다른 트랜잭션 속성과의 관계
트랜잭션 원자성은 ACID 트랜잭션 특성 중 하나로, 나머지 세 가지 속성인 일관성, 격리성, 지속성과 밀접하게 연관되어 작동한다. 원자성은 트랜잭션의 모든 연산이 완전히 수행되거나 전혀 수행되지 않음을 보장하는 반면, 다른 속성들은 이 보장을 바탕으로 데이터의 정합성과 신뢰성을 확장한다.
원자성은 일관성과 지속성을 실현하기 위한 핵심 기반이다. 일관성은 트랜잭션이 데이터베이스의 사전 정의된 규칙(제약 조건)을 위반하지 않은 상태로 종료되어야 함을 의미한다. 원자성이 보장되지 않으면 트랜잭션의 중간 상태가 데이터베이스에 부분적으로 반영되어 일관성이 깨질 수 있다. 지속성은 커밋된 트랜잭션의 결과가 시스템 장애 후에도 영구적으로 유지됨을 보장한다. 원자성은 커밋 전의 모든 변경 사항을 안전하게 기록(예: WAL)하여, 커밋이 확정된 작업만이 지속성의 보호를 받도록 한다.
격리성은 동시에 실행되는 여러 트랜잭션이 서로 간섭하지 않도록 관리하는 속성이다. 원자성과 격리성은 상호 보완적 역할을 한다. 격리성 수준(예: Read Committed, Serializable)에 따라 다른 트랜잭션이 부분적으로 커밋된 데이터를 볼 수 없도록 보장하는 데, 이 부분적 커밋 상태 자체가 원자성에 의해 존재하지 않게 된다. 따라서 높은 격리성 수준은 원자성의 완전한 'all-or-nothing' 실행을 전제로 더 엄격한 동시성 제어를 구현한다.
ACID 속성 간의 관계는 다음 표로 요약할 수 있다.
속성 | 핵심 개념 | 원자성과의 관계 |
|---|---|---|
일관성 (Consistency) | 트랜잭션 전후 데이터베이스 규칙 준수 | 원자성이 부분 완료를 방지하여 일관성 상태 도달 보장 |
격리성 (Isolation) | 동시 실행 트랜잭션의 간섭 방지 | 원자성은 격리성 구현을 위한 논리적 단위(트랜잭션) 제공 |
지속성 (Durability) | 커밋된 결과의 영구 저장 | 원자성은 커밋 완료된 작업만을 지속성의 대상으로 만듦 |
결론적으로, 원자성은 트랜잭션을 하나의 불가분한 작업 단위로 정의함으로써, 다른 ACID 속성들이 효과적으로 구현될 수 있는 토대를 마련한다. 이들 속성은 분리되어 작동하지 않고 통합적으로 데이터베이스 시스템의 신뢰성을 구성한다.
5.1. 일관성, 격리성, 지속성 (ACID)
5.1. 일관성, 격리성, 지속성 (ACID)
트랜잭션의 핵심 속성인 ACID에서 원자성은 나머지 세 속성인 일관성, 격리성, 지속성과 밀접하게 연관되어 있으며, 함께 작동하여 신뢰할 수 있는 데이터 처리를 보장한다.
원자성은 일관성과 지속성을 달성하기 위한 필수 전제 조건이다. 트랜잭션이 원자적으로 실행되지 않으면(즉, 부분적으로만 적용된다면), 데이터베이스는 사전 정의된 무결성 제약 조건을 위반한 불일치 상태에 빠질 수 있다. 예를 들어, 계좌 이체 트랜잭션에서 출금만 성공하고 입금이 실패하면 총 금액의 보존이라는 일관성 규칙이 깨진다. 또한, 원자성은 "모두 아니면 전무"의 결과를 보장함으로써, 트랜잭션 커밋 시 그 변경 사항이 영구적으로 기록된다는 지속성의 범위를 명확히 정의하는 역할을 한다.
격리성은 동시에 실행되는 여러 트랜잭션이 서로에게 미치는 영향을 제어하는 속성이다. 원자성은 단일 트랜잭션의 내부적 완결성을 다루는 반면, 격리성은 여러 트랜잭션 간의 상호 작용을 관리한다. 높은 수준의 격리성(예: 직렬화 가능)은 각 트랜잭션이 원자적으로 실행되는 것처럼 보이게 하여, 동시성 제어 메커니즘(예: 락킹)을 통해 원자성의 효과를 유지한다. 그러나 격리성 수준을 낮추면 성능은 향상될 수 있지만, 다른 트랜잭션에 의해 중간 상태가 노출될 위험이 생겨 원자성의 지각적 보장이 약화될 수 있다.
ACID 속성 간의 관계는 다음 표로 요약할 수 있다.
속성 | 핵심 개념 | 원자성과의 관계 |
|---|---|---|
일관성 (Consistency) | 트랜잭션 전후 데이터베이스가 모든 규칙을 준수한 상태. | 원자성이 보장되지 않으면 일관성 있는 최종 상태를 달성할 수 없다. |
격리성 (Isolation) | 동시 실행 트랜잭션이 서로 간섭하지 않음. | 원자적인 단위가 격리되어 실행되도록 하여 부분적 결과 노출을 방지한다. |
지속성 (Durability) | 커밋된 트랜잭션의 결과는 영구적임. | 원자성은 '커밋'될 전체 작업 단위를 정의하며, 이 단위가 지속성의 대상이 된다. |
6. 실패 시나리오와 복구
6. 실패 시나리오와 복구
트랜잭션의 원자성이 깨지는 실패는 주로 시스템 장애, 하드웨어 문제, 소프트웨어 버그, 또는 네트워크 분할로 인해 발생한다. 이러한 실패는 트랜잭션의 일부 연산만 적용된 상태, 즉 중간 상태를 데이터베이스에 남길 수 있다. 이는 데이터베이스 일관성을 심각하게 훼손한다.
복구 메커니즘은 이러한 중간 상태를 감지하고 원자성을 복원하는 역할을 한다. 가장 일반적인 접근법은 로그 기반 복구를 활용하는 것이다. 시스템은 트랜잭션 시작 전에 로그에 시작 기록을, 연산 수행 시 변경 사항을 리두 로그에, 그리고 완료 시 커밋 기록을 순차적으로 남긴다. 시스템 장애 후 재시작 시, 복구 관리자는 로그를 분석한다. 커밋 기록이 있는 트랜잭션의 변경 사항은 리두 로그를 통해 재적용하고(Redo), 커밋 기록 없이 종료된 트랜잭션의 부분적 변경 사항은 언두 로그를 이용해 원래 상태로 되돌린다(Undo).
실패 유형 | 주요 원인 | 복구 절차의 핵심 목표 |
|---|---|---|
시스템 크래시 | 하드웨어 고장, 운영체제 오류 | 로그 스캔을 통한 Redo(재실행)와 Undo(취소) 수행 |
트랜잭션 실패 | 논리적 오류(예: 제약 조건 위반), 데드락 | 해당 트랜잭션의 효과를 완전히 Undo하여 마치 실행되지 않은 것처럼 만듦 |
미디어 실패 | 디스크 손상 | 정기적으로 생성한 백업과 아카이브 로그를 이용해 데이터베이스를 장애 이전 시점으로 복원 |
분산 환경에서의 복구는 더욱 복잡하다. 2단계 커밋 프로토콜을 사용하는 중 코디네이터 또는 참여자 노드에 장애가 발생하면, 프로토콜은 차단 상태에 빠질 수 있다. 이를 해결하기 위해 새로운 코디네이터가 선출되어 로그를 조회하고, 모든 참여자의 상태를 폴링하여 트랜잭션을 최종 커밋 또는 중단시키는 과정이 필요하다[5]. 이러한 복구 절차는 데이터의 원자성과 트랜잭션 지속성을 보장하는 데 필수적이다.
7. 여담
7. 여담
트랜잭션 원자성의 개념은 컴퓨터 과학 외의 다양한 분야에서도 발견된다. 예를 들어, 데이터베이스 트랜잭션과 유사하게, 은행의 계좌 이체는 출금과 입금이 모두 성공하거나 모두 실패해야 하는 원자적 작업이다.
이 개념은 일상 생활의 많은 약속이나 계약에도 적용될 수 있다. "A를 하면 B를 한다"와 같은 조건부 계약은 A와 B가 하나의 원자적 단위로 처리되어야 완전히 이행된 것으로 간주된다[6].
컴퓨터 과학의 초기부터, 시스템 장애 시에도 데이터 무결성을 보장해야 할 필요성은 인식되어 왔다. 이는 ACID 모델의 정립으로 이어졌으며, 원자성은 그 핵심 기둥 중 하나가 되었다.
