ACID
"오늘의AI위키"의 AI를 통해 더욱 풍부하고 폭넓은 지식 경험을 누리세요.
1. 개요
ACID는 데이터베이스 트랜잭션의 네 가지 속성, 즉 원자성(Atomicity), 일관성(Consistency), 격리성(Isolation), 지속성(Durability)을 의미한다. 원자성은 트랜잭션 내 모든 연산이 성공하거나 실패해야 함을 보장하며, 일관성은 트랜잭션 전후 데이터베이스의 일관성을 유지한다. 격리성은 동시 실행되는 트랜잭션 간의 간섭을 방지하고, 지속성은 트랜잭션 커밋 후 시스템 오류에도 데이터가 유지되도록 보장한다. ACID 속성은 데이터베이스의 무결성과 신뢰성을 확보하는 데 중요한 역할을 하며, 분산 환경에서의 구현은 복잡하며 2단계 커밋 프로토콜과 같은 기술이 사용된다.
Reuter와 Härder가 정의한 트랜잭션의 네 가지 속성은 다음과 같다. 데이터베이스에서 데이터에 대한 하나의 논리적 조작을 트랜잭션이라고 부른다.
2. ACID의 속성
2. 1. 원자성 (Atomicity)
트랜잭션은 여러 개의 구문으로 구성되는 경우가 많다. 원자성(Atomicity)은 각 트랜잭션을 하나의 "단위"로 취급하여, 트랜잭션에 포함된 모든 연산이 전부 성공하거나 아니면 전부 실패하는 것('All or Nothing')을 보장하는 성질이다.[4][8] 원자성은 불가분성이라고도 불린다. 즉, 트랜잭션을 구성하는 구문 중 하나라도 완료되지 않으면 전체 트랜잭션이 실패하고 데이터베이스는 변경되지 않은 상태로 유지된다. 원자성 보장은 데이터베이스 업데이트가 부분적으로만 발생하는 것을 방지하며, 이는 전체 연산을 거부하는 것보다 더 큰 문제를 야기할 수 있다.[4][8] 따라서 원자성은 데이터베이스가 항상 일관된 상태를 유지하도록 돕는다.[9]
원자적 시스템은 정전, 오류, 충돌 등 어떤 상황에서도 원자성을 보장해야 한다.[4] 또한, 트랜잭션은 다른 데이터베이스 클라이언트에게 진행 중인 상태로 관찰될 수 없다. 어느 시점에는 아직 발생하지 않았고, 다음 시점에는 이미 전체적으로 발생했거나 (트랜잭션이 취소된 경우) 아무 일도 일어나지 않은 것으로 보인다.[4]
원자적 트랜잭션의 대표적인 예시는 은행 계좌 이체이다. 계좌 A에서 계좌 B로 특정 금액(예: 10000JPY)을 송금하는 경우를 생각해보자. 이 작업은 다음 두 가지 연산으로 구성된다.
# 계좌 A의 잔고에서 10000JPY을 뺀다.
# 계좌 B의 잔고에 10000JPY을 더한다.
원자성은 이 두 연산이 반드시 함께 성공하거나 함께 실패하도록 보장한다. 만약 계좌 A에서 돈을 빼는 데는 성공했지만, 시스템 오류 등으로 계좌 B에 돈을 더하는 데 실패하면, 이체 작업 전체가 취소되어 계좌 A의 잔고는 원래대로 돌아간다. 이렇게 함으로써 어느 한쪽 연산만 실행되어 은행 전체의 예금 잔고에 모순이 생기는 상황을 방지한다.[9]
2. 2. 일관성 (Consistency)
일관성은 트랜잭션이 실행되기 전과 후에 데이터베이스 상태가 미리 정의된 규칙과 제약 조건을 항상 만족해야 한다는 원칙이다. 이는 데이터베이스의 불변성을 유지하여, 유효하지 않은 데이터로 인해 데이터베이스가 손상되는 것을 방지하고 데이터 무결성을 보장하는 역할을 한다.[5]
데이터베이스에 기록되는 모든 데이터는 무결성 제약 조건, 연쇄, 트리거 등 정의된 모든 규칙에 따라 유효해야 한다. 예를 들어, 참조 무결성은 기본 키와 외래 키 간의 관계가 항상 유효하게 유지되도록 보장하는 대표적인 데이터베이스 불변성 규칙이다.[5]
일관성은 데이터가 모든 유효성 검사 규칙을 충족해야 함을 의미한다. 예를 들어, 데이터베이스에 '계좌 A와 계좌 B의 잔액 합은 항상 100이어야 한다' (''A'' + ''B'' = 100)는 규칙이 있다고 가정해 보자. 만약 어떤 트랜잭션이 ''B''는 그대로 두고 ''A''의 잔액만 10 줄이려고 시도하면, 트랜잭션 자체는 성공적으로 실행될 수 있다 (원자성 만족). 하지만 트랜잭션 완료 후 데이터베이스 상태를 검사하면 ''A'' + ''B'' = 90이 되어 미리 정의된 규칙(''A'' + ''B'' = 100)을 위반하게 된다. 이 경우, 데이터베이스 시스템은 일관성을 유지하기 위해 해당 트랜잭션의 모든 변경 사항을 취소하고 데이터를 트랜잭션 시작 전의 상태로 되돌린다(롤백).[5]
데이터 유형 제약(예: 특정 컬럼에는 정수만 입력 가능)이나 외래 키 제약(예: 다른 테이블에서 참조하는 행은 삭제 불가) 등 다른 종류의 제약 조건 위반 시에도 마찬가지로 트랜잭션이 중단되거나 롤백된다. 또한, '계좌 잔액은 항상 0 이상이어야 한다'는 규칙이 있다면, 잔액을 음수로 만드는 송금 트랜잭션은 일관성 원칙에 따라 거부된다. 즉, 데이터베이스의 규칙(일관성 조건)을 만족하지 않는 상태를 초래하는 트랜잭션은 실행되지 않는다.[5]
일관성은 일본어로 整合性|세이고세이일본어라고도 한다.
2. 3. 격리성 (Isolation)
트랜잭션은 종종 동시에 실행된다. 예를 들어, 여러 트랜잭션이 동시에 특정 테이블을 읽고 쓰는 경우가 있다. 격리성(Isolation)은 이렇게 동시에 여러 트랜잭션이 실행될 때, 마치 각 트랜잭션이 순서대로 하나씩 실행된 것처럼 데이터베이스 상태를 동일하게 유지하도록 보장하는 속성이다. 즉, 트랜잭션 실행 중에는 다른 트랜잭션의 간섭을 받지 않고 독립적으로 실행되는 것을 의미한다. 격리성은 동시성 제어의 주요 목표 중 하나이며, 설정된 격리 수준에 따라 아직 완료되지 않은 트랜잭션의 중간 결과가 다른 트랜잭션에게 보이지 않을 수 있다.[6]
격리성을 이해하기 위해, 동일한 데이터를 수정하려는 두 개의 트랜잭션 T1과 T2가 동시에 실행되는 상황을 가정해 보자. 격리성을 유지하려면 둘 중 하나의 트랜잭션은 다른 트랜잭션이 완료될 때까지 기다려야 한다.
예를 들어 다음과 같은 두 트랜잭션을 생각해 볼 수 있다.
만약 이 작업들이 순서대로 실행된다면(예: T1 완료 후 T2 실행), 격리성은 유지된다. 만약 T1이 실행 도중에 실패하더라도, 데이터베이스는 T1의 변경 사항을 모두 취소(롤백)하여 T2는 일관성 있는 데이터만 보게 된다.
하지만 트랜잭션 작업들이 뒤섞여 실행될 경우 문제가 발생할 수 있다. 예를 들어 다음과 같은 순서로 작업이 진행된다고 가정해 보자.
# T1: 계좌 A에서 10을 뺀다.
# T2: 계좌 B에서 20을 뺀다.
# T2: 계좌 A에 20을 더한다. (T2 완료)
# T1: 계좌 B에 10을 더한다.
만약 4단계에서 T1이 실패한다면 어떻게 될까? T2는 이미 T1이 변경한 A 값을 기반으로 계산을 완료하고 커밋했을 수 있다. 이 상태에서는 T1의 변경 사항만 원래대로 되돌리는 것이 어려워 데이터베이스 상태가 비일관적이 될 수 있다. 이러한 문제를 쓰기-쓰기 충돌이라고 부르며, 두 트랜잭션이 동시에 같은 데이터 항목을 수정하려고 할 때 발생한다.[10] 일반적인 시스템에서는 이런 문제가 발생하면, 마지막으로 확인된 정상 상태로 데이터베이스를 되돌리고, 실패한 트랜잭션 T1을 취소하며, T1의 영향으로 중단된 T2와 같은 다른 트랜잭션들을 정상 상태에서 다시 시작하여 문제를 해결한다.
격리성은 트랜잭션이 수행하는 작업 과정이 다른 트랜잭션에게 보이지 않도록 숨기는 것을 의미한다. 일본어로는 分離性|분리성일본어, 独立性|독립성일본어 또는 隔離性|격리성일본어이라고도 한다. 더 엄밀하게는, 격리성이란 트랜잭션 실행 기록(로그)이 직렬화 가능(Serializable)하다는 것을 의미한다. 하지만 높은 수준의 격리성은 시스템 성능 저하를 일으킬 수 있는 트레이드 오프 관계에 있기 때문에, 실제 데이터베이스 시스템에서는 성능 향상을 위해 격리 수준을 다소 완화하여 구현하는 경우가 많다.
다른 예시로, 계좌 A의 잔고가 100만엔이고 계좌 B의 잔고가 200만엔일 때, A에서 B로 1만엔를 송금하는 트랜잭션을 생각해 보자. 이 트랜잭션은 내부적으로 다음과 같은 순서로 작업을 수행할 수 있다.
# 계좌 A의 잔고에서 1만엔를 뺀다.
# 계좌 B의 잔고에 1만엔를 더한다.
이때 데이터베이스 내부 상태는 다음과 같이 변할 수 있다.
격리성이 보장된다면, 다른 트랜잭션이나 외부 관찰자는 오직 '송금 전' 상태 또는 '송금 후' 상태만 볼 수 있으며, '실행 중' 상태와 같은 중간 단계의 불완전한 상태는 관찰할 수 없다.
2. 4. 지속성 (Durability)
지속성(Durability)은 트랜잭션이 성공적으로 완료(커밋)되면, 이후 시스템 장애(예: 정전 또는 시스템 충돌)가 발생하더라도 그 결과가 영구적으로 유지되는 것을 보장하는 특성이다.[7] 즉, 한번 완료된 트랜잭션의 결과는 시스템에 문제가 생겨도 사라지지 않고 보존된다는 의미이다.예를 들어, 사용자 A가 사용자 B에게 10원을 이체하는 트랜잭션을 성공적으로 마쳤다는 알림을 받았다고 가정해 보자. 이 시점에서 실제 데이터 변경 사항은 아직 디스크 버퍼에만 기록되어 있고, 영구 저장 장치인 디스크에는 기록되지 않았을 수 있다. 만약 이때 갑자기 전원이 꺼지면 버퍼의 내용은 사라지지만, 사용자는 이미 이체가 완료되었다고 알고 있기 때문에 데이터가 유지될 것이라고 기대한다. 지속성은 바로 이러한 상황에서 데이터가 실제로 안전하게 보존됨을 보장하는 역할을 한다.
일반적으로 지속성은 완료된 트랜잭션의 내용을 비휘발성 메모리에 기록하는 방식으로 구현된다. 많은 DBMS는 트랜잭션 작업 내용을 로그(log)로 영속성 저장 장치에 기록한다. 만약 시스템에 문제가 발생하면, 이 로그를 사용하여 시스템 이상 발생 직전의 상태로 데이터를 복구함으로써 지속성을 확보한다.[7] 또한, DBMS는 무결성 제약을 확인하여 트랜잭션이 안전하게 완료될 수 있도록 보장한다.
온라인 쇼핑몰에서 상품 구매를 완료한 경우를 생각해 볼 수 있다. 결제가 성공적으로 끝나면, 설령 쇼핑몰 서버에 오류가 발생하더라도 사용자의 구매 내역과 결제 정보는 안전하게 보존되어야 한다. 이것이 바로 지속성이 보장되는 예시다.
3. 구현
ACID 속성을 구현하는 것은 간단한 문제가 아니다. 트랜잭션 처리는 인덱스 업데이트를 포함하여 데이터베이스 내부에 많은 변경을 필요로 한다. 트랜잭션을 처리하는 과정은 여러 이유로 실패할 수 있는데, 예를 들어 시스템의 디스크 공간 부족이나 할당된 CPU 시간 초과 등이 원인이 될 수 있다.[4]
ACID 속성, 특히 원자성과 영속성을 보장하기 위해 널리 사용되는 두 가지 기술은 로그 선행 기록(Write-Ahead Logging, WAL)과 섀도 페이징(Shadow Paging)이다. 두 방식 모두 업데이트할 데이터에 락(lock)을 거는 것이 필요하며, 격리 수준에 따라서는 읽기만 하는 데이터에도 락이 필요할 수 있다.
- 로그 선행 기록 (WAL): 데이터베이스를 직접 변경하기 전에 모든 변경 예정 사항(재실행(redo) 및 취소(undo) 정보 포함)을 로그 파일에 먼저 기록한다. 이를 통해 시스템 충돌이 발생하더라도 로그를 사용하여 데이터베이스를 일관된 상태로 복구할 수 있어 원자성과 영속성을 보장한다.[4]
- 섀도 페이징: 변경 사항을 데이터베이스의 현재 복사본이 아닌 별도의 페이지(섀도 페이지)에 기록한다. 트랜잭션이 성공적으로 완료(커밋)되면, 이 새로운 페이지들을 가리키도록 포인터를 갱신하여 변경 사항을 한 번에 반영한다. 변경되지 않은 데이터는 이전 버전을 그대로 참조한다.
격리성을 포함한 ACID 속성을 보장하기 위해 전통적으로 많은 데이터베이스 시스템은 잠금(Locking) 메커니즘에 의존해왔다. 특정 데이터에 접근하려는 트랜잭션은 해당 데이터에 잠금을 설정하여 다른 트랜잭션의 동시 수정을 막는다. 읽기 작업 시에도 잠금이 필요할 수 있다. 하지만 잠금 방식은 여러 트랜잭션이 동일 데이터에 접근하려 할 때 대기 상태를 유발하여 동시성을 저해하고 시스템 전체 성능을 떨어뜨릴 수 있다. 예를 들어, 한 트랜잭션이 특정 데이터를 읽고 있는 동안 다른 트랜잭션이 해당 데이터를 수정하려면 앞선 트랜잭션이 끝날 때까지 기다려야 한다. 완전한 격리성을 보장하기 위해 2단계 잠금(Two-Phase Locking, 2PL) 기법이 사용되기도 한다.[4]
잠금 방식의 단점을 보완하기 위해 다중 버전 동시성 제어(Multi-Version Concurrency Control, MVCC) 방식이 널리 사용된다. MVCC는 데이터를 수정할 때마다 새로운 버전을 생성하여 관리한다. 읽기 트랜잭션은 특정 시점의 데이터 스냅샷을 읽게 되므로, 다른 트랜잭션이 데이터를 수정하더라도 잠금 없이 일관된 데이터를 읽을 수 있다. 즉, 읽기 작업이 쓰기 작업을 차단하거나, 쓰기 작업이 읽기 작업을 차단하는 현상이 줄어들어 동시성이 크게 향상된다. 예시로 돌아가서, 사용자 A의 트랜잭션이 사용자 B가 수정하고 있는 데이터를 요청하면 데이터베이스는 A에게 사용자 B가 트랜잭션을 시작했을 때 존재했던 해당 데이터의 버전을 제공한다. 사용자 A는 다른 사용자가 데이터를 변경하더라도 일관된 데이터베이스 보기를 얻는다. 한 가지 구현 방식인 스냅샷 격리(Snapshot Isolation)는 격리 속성을 완화한다.[4]
분산 데이터베이스 환경에서는 네트워크 문제나 여러 노드에서의 동시 작업으로 인해 ACID 속성을 보장하는 것이 더욱 복잡하다. 여러 시스템에 걸쳐 있는 트랜잭션의 원자성을 보장하기 위해 2단계 커밋(Two-Phase Commit, 2PC) 프로토콜 등이 사용된다. 2PC는 트랜잭션에 참여하는 모든 노드가 만장일치로 커밋에 동의해야만 최종적으로 변경 사항을 반영하도록 조율한다.
엄격하게 ACID 속성을 모두 구현하는 것은 상당한 시스템 자원을 소모하고 성능 저하를 유발할 수 있다. 예를 들어, 높은 격리성 수준을 유지하기 위해 광범위한 잠금을 사용하면 동시성이 떨어지고, 영속성을 위해 모든 변경 사항을 즉시 디스크에 기록하면 입출력 병목 현상이 발생할 수 있다. 따라서 실제 시스템에서는 성능과의 트레이드 오프를 고려하여 특정 ACID 속성, 특히 격리 수준을 다소 완화하여 구현하는 경우가 많다.
4. 분산 환경에서의 ACID
네트워크 환경에서는 ACID 속성을 보장하기 더 어렵다. 네트워크 연결이 끊어지거나, 여러 사용자가 동시에 데이터베이스의 같은 부분에 접근하려 할 수 있기 때문이다.
특히, 여러 노드에 데이터가 분산되어 있는 분산 데이터베이스 환경에서는 분산 트랜잭션의 ACID 속성을 지키는 것이 더욱 복잡하다. 예를 들어, 네트워크 연결이 실패하거나, 한 노드가 트랜잭션 일부를 성공적으로 마쳤지만 다른 노드에서 오류가 발생하여 전체 작업을 되돌려야 하는(롤백) 상황이 생길 수 있다.
이러한 문제를 해결하기 위해 분산 트랜잭션에서는 2단계 커밋 프로토콜(Two-Phase Commit, 2PC)을 사용한다. 2단계 커밋은 트랜잭션에 참여하는 모든 노드가 작업을 최종적으로 확정(커밋)할지 아니면 취소(롤백)할지에 대해 만장일치로 동의하도록 보장하여 원자성을 확보하는 방법이다.[11] (이는 2단계 잠금과는 다른 개념이므로 혼동하지 않도록 주의해야 한다.)
간단히 설명하면, 2단계 커밋 프로토콜은 다음과 같이 동작한다.
# 준비 단계 (Prepare Phase): 조정자(coordinator) 노드가 모든 참여자(participant) 노드에게 트랜잭션을 커밋할 준비가 되었는지 묻는다. 참여자들은 작업을 완료할 수 있으면 '준비 완료'를, 그렇지 않으면 '거부'를 응답한다.
# 커밋 단계 (Commit Phase): 조정자는 모든 참여자로부터 '준비 완료' 응답을 받으면, 모든 노드에 커밋 명령을 보낸다. 만약 한 명이라도 '거부'를 응답하거나 시간 내에 응답하지 않으면, 조정자는 모든 노드에 롤백 명령을 보낸다.
5. ACID와 다른 모델
6. 트랜잭션을 고려한 파일 시스템 (참고)
참조
[1]
논문
Principles of transaction-oriented database recovery
[2]
간행물
The Transaction Concept: Virtues and Limitations
http://research.micr[...]
Tandem Computers
2015-03-27
[3]
서적
Distributed Transaction Processing: Concepts and Techniques
https://archive.org/[...]
Morgan Kaufmann
1993
[4]
웹사이트
Atomic operation
http://www.webopedia[...]
Webopedia
2003-11-25
[5]
문서
SQL and Relational Theory: How to Write Accurate SQL Code 2nd edition
O'reilly Media, Inc.
2012
[6]
웹사이트
Isolation Levels in the Database Engine
https://learn.micros[...]
2023-07-14
[7]
서적
Database system concepts
https://www.worldcat[...]
McGraw-Hill
2011
[8]
웹사이트
Atomicity
https://docs.oracle.[...]
2016-12-13
[9]
웹사이트
Atomic File Transactions, Part 1
http://archive.oreil[...]
2016-02-28
[10]
서적
Database system concepts
https://www.worldcat[...]
McGraw-Hill
2011
[11]
서적
Principles of Transaction Processing
http://www.elsevierd[...]
Morgan Kaufmann (Elsevier)
2009
[12]
문서
ISO/IEC 10026-1:1992 Section 4
[13]
문서
Andreas Reuter
[14]
문서
Theo Härder
[15]
URL
http://commons.apach[...]
[16]
문서
basically available, soft state
[17]
웹인용
Gray to be Honored With A. M. Turing Award This Spring
http://www.microsoft[...]
Microsoft PressPass
1998-11-23
[18]
간행물
The Transaction Concept: Virtues and Limitations
http://research.micr[...]
Tandem Computers
2006-11-09
[19]
문서
Distributed Transaction Processing: Concepts and Techniques
Morgan Kaufmann
1993
[20]
저널
Principles of transaction-oriented database recovery
https://archive.org/[...]
본 사이트는 AI가 위키백과와 뉴스 기사,정부 간행물,학술 논문등을 바탕으로 정보를 가공하여 제공하는 백과사전형 서비스입니다.
모든 문서는 AI에 의해 자동 생성되며, CC BY-SA 4.0 라이선스에 따라 이용할 수 있습니다.
하지만, 위키백과나 뉴스 기사 자체에 오류, 부정확한 정보, 또는 가짜 뉴스가 포함될 수 있으며, AI는 이러한 내용을 완벽하게 걸러내지 못할 수 있습니다.
따라서 제공되는 정보에 일부 오류나 편향이 있을 수 있으므로, 중요한 정보는 반드시 다른 출처를 통해 교차 검증하시기 바랍니다.
문의하기 : help@durumis.com