[Database] Transaction에 대하여 1편 - 트랜잭션과 ACID
0. 들어가며 🏃🏻♂️
이번 글은 데이터베이스의 트랜잭션 개념에 대해 가볍게 공부해보려다가 결국 데이터베이스 전공책을 펴게된 김에 정리하게 되었습니다.
본 글은 DATABASE SYSTEM CONCEPTS 7th edition의 Chapter 17. Transaction 내용을 나름대로 번역 + 요약 + 변형한 글입니다.
1. 트랜잭션와 ACID 😎
데이터베이스에서 실행되는 여러 연산은 사용자 입장에서는 하나의 단위로 보이는 경우가 있습니다. 대표적으로 송금이 그 예시이죠. 사실 송금이라는 행위는 한 계좌를 읽고, 돈을 빼고, 다른 계좌를 읽고, 돈을 넣고 등의 행위를 해야합니다. 허나 사용자 입장에서는 논리적으로 하나의 단위인 행위이죠. 이처럼 하나의 논리적 작업 단위를 이루는 연산의 집합을 트랜잭션이라고 합니다.
트랜잭션은 SQL이나 JDBC 같은 사용자 프로그램에 의해 수행됩니다. 보통 아래 예시처럼 구성되어있죠.
begin transaction
연산1
연산2
연산3
...
end transaction
이러한 트랜잭션은 ACID라고 불리는 중요한 특성을 만족해야합니다. 각각에 대해 알아보도록 하겠습니다.
1) 원자성 (Atomicity)
✅ 트랜잭션은 연산의 집합이라고 했습니다. 이러한 연산의 집합은 사용자에게는 하나의 나눌 수 없는 단위로 보여야한다는 것이 바로 원자성입니다. 또한 트랜잭션은 원자성, 즉 나눌 수 없으므로 전부 실행되거나 전부 실행되지 않아야하죠. 따라서 트랜잭션이 실행됐지만, 어떤 이유로 실패하게되면 데이터베이스에 행했던 모든 변경을 되돌려야 합니다. 즉, 트랜잭션은 All or None 으로 작동해야합니다.
2) 일관성 (Consistency)
✅ 트랜잭션이 데이터베이스 일관성을 보존해야한다는 특성입니다. 한 트랜잭션이 일관된 상태의 데이터베이스에서 원자적이고 고립된 상태에서 실행됐다면, 트랜잭션이 종료된 이후에도 데이터베이스는 일관된 상태를 유지해야한다는 것이죠. 저는 이 말이 조금 어려웠는데, 간단한 예시로는 Primary key 제약조건, Foreign key 제약조건과 같은 데이터 무결성 제약조건을 트랜잭션 전후로 유지해야한다라는 것이 있습니다. 이외에도 개발자의 책임으로 지켜지는 일관성도 존재하죠. 이 예시는 뒤에서 살펴보겠습니다.
3)고립성 (Isolation)
✅ 고립성은 여러 트랜잭션이 데이터베이스에서 동시에 수행될 때 지켜져야할 특성입니다. 트랜잭션 T1, T2가 동시에 수행된다면 데이터 베이스에 반영된 결과는 T1 ➡️ T2 순 혹은 T2 ➡️ T1 순으로 수행되었을 때와 같아지도록 보장해야합니다. 즉, 서로 다른 트랜잭션은 동시에 수행되는지 모르며, 마치 순차적으로 실행된 것과 같은 결과를 내야하는 것이죠.
4) 지속성 (Durablity)
✅ 지속성은 트랜잭션이 성공적으로 수행되고 나면, 트랜잭션에 의해 반경된 데이터베이스 내용은 영구적으로 반영되야 한다는 것입니다. 이 부분은 당연해보이죠?
2. 간단한 트랜잭션 모델 예시와 함께 보는 ACID 📖
앞서 살펴본 것처럼 ACID의 특성을 저정도 말로만 알고 넘어가면 조금 아쉽습니다. 따라서 간단한 트랜잭션 사례를 통해 트랜잭션이 ACID 특징을 왜 지켜야하는지에 대해 알아보도록 하겠습니다.
간단한 송금 상황을 트랜잭션으로 표현하면 아래와 같습니다.
# 김씨 계좌에서 이씨 계좌로 만원을 송금하는 상황
begin Transaction
1. 변수 A에 김씨의 잔액을 가져온다.
2. A = A - 10,000
3. A를 김씨 계좌 잔액으로 수정한다.
4. 변수 B에 이씨의 잔액을 가져온다.
5. B = B + 10,000
6. B를 이씨 계좌 잔액으로 수정한다.
end Transaction
위와 같은 상황에서 ACID 특성이 왜 필요한지에 대해 알아보도록 하겠습니다. 설명의 편의를 위해 A-C-I-D 순서와는 다르게 살펴보도록 하겠습니다.
우선 일관성입니다. 이 예시에서 일관성 조건은 김씨 계좌와 이씨 계좌의 잔액 합이 트랜잭션 전후로 같아야한다는 것입니다. 이 일관성 조건이 없다면 송금 트랜잭션에 의해 돈이 늘어나거나 없어질 수도 있겠죠. 앞서 살펴본 것처럼 일관성은 데이터베이스의 무결성 제약조건을 지켜야한다와 같은 내용도 있지만 SQL로 기술할 수 없는, 즉 트랜잭션을 작성하는 개발자의 올바른 행위까지 포함하는 넓은 개념인 것 같습니다.
그 다음은 원자성입니다. 송금 트랜잭션에서 원자성이 지켜지지 않으면 어떻게 될까요? 만약 3번까지의 행위가 이루어지고, 트랜잭션이 어떠한 오류로 중간에 끝나버린다면 김씨의 잔액만 만원이 빠져나가고 이씨의 잔액은 오르지 않는 큰 문제가 발생해버립니다. 따라서 트랜잭션의 연산 집합 모두를 실행 시키지 못했다면 기존에 했던 행위를 다 취소해야합니다. 아주 중요한 특징으로 보이죠. 데이터베이스에서 원자성을 보장하기 위한 기본 방법은 다음과 같습니다. 데이터베이스 시스템은 트랜잭션이 데이터에 write를 하게되면 이전 값을 log라는 파일에 기록해둡니다. 트랜잭션이 정상적으로 수행되지 못한 경우 이 log 파일을 이용해 데이터를 이전 값으로 복구함으로써 트랜잭션이 실행되지 않았던 것처럼 해주는 것이죠.
다음 특성으로는 지속성이 있었죠. 지속성은 간단한데요. 트랜잭션이 완료되고나면 당연히 데이터베이스에는 그 결과가 지속되어야합니다. 지속성이 만족되지 못한다면 위 예시에서는 송금을 했는데도 그 정보가 지속되지않아 갑자기 송금전으로 돌아가거나 하는 문제가 발생할 수 있겠죠.
마지막은 고립성입니다. 고립성이 보장되지 않는다면 다음과 같은 문제가 생깁니다. 상황을 가정해보도록 하죠. 예시 트랜잭션이 실행되는 중간에 다른 트랜잭션 T2(이씨에게 2만원 송금)가 동시에 수행된다고 생각해봅시다. 그리고 예시 트랜잭션의 5번 행위를 수행하기 전에 T2가 이씨의 잔액을 읽고, 예시 트랜잭션이 끝난후 T2가 이씨 잔액에서 2만원을 추가한다고 하면 문제가 발생합니다. 이씨 잔액은 총 3만원이 증가했어야하는데 T2의 행위였던 2만원 송금만 반영이되어 이씨 잔액이 2만원만 증가되어버리는 경우가 생길 수 있습니다. 이런 문제를 해결하기 위해 데이터베이스는 고립성이라는 특징을 유지해야하고, 이 부분을 Concurrency control system이라고 불리는 데이터베이스 시스템 구성요소가 책임지고 있습니다.
여기까지 데이터베이스 트랜잭션과 ACID가 무엇인지, 그리고 ACID라는 특징을 왜 지켜야하는지에 대해 알아보았습니다.
감사합니다.