
트랜잭션(Transaction)
트랜잭션은 DB에서 하나의 논리적 작업 단위(a unit of work)를 얘기합니다. 이 단위 안에는 한 가지의 요청(INSERT, UPDATE, DELETE 등)만 있을 수 있고, 여러가지 요청이 포함되어 있을 수 있죠.
이런 트랜잭션은 데이터의 무결성(Integrity)을 보장하기 위해서 ACID라는 특성을 가지고 있는데요. 오늘은 이 네 가지 특성에 대해서 알아볼까합니다.
원자성(Atomicity)

원자성(Atomicity)은 한마디로 '전부 성공하거나, 아니면 아예 실행되지 않거나(All or Nothing)'로 정리할 수 있습니다. 예를 들어, 한 트랜잭션에서 100가지 종류의 음식을 저장한다고 가정해 봅시다. 99가지는 저장되었지만, 마지막 딱 1가지에서 오류가 발생했다면 어떻게 될까요? 데이터베이스는 앞선 99가지의 성공을 전부 무효화하고, 아예 처음 상태로 되돌려(Rollback) 버립니다.
99개나 성공했는데, 왜 이렇게 냉정하게 전부 폐기 처분하는 걸까요?
대표적인 이유로는 데이터의 불일치(Data Inconsistency)를 막기 위해서입니다. 예를 들어서 100개의 음식을 주문한 사람이 있습니다. 주방 사정으로 99개는 성공적으로 요리되었지만, 마지막 1개의 재료가 떨어져 실패했습니다. 식당이 그냥 99개만 쓱 내놓는다면 손님 입장에서는 주문이 제대로 처리되지 않아 화가 나겠죠?
데이터베이스도 마찬가지입니다. 일부만 반영되어 시스템의 상태가 오염 되는 것을 막기 위해, 하나라도 실패하면 롤백(Rollback)을 통해 주문 자체를 아예 안 들어온 처음 상태로 되돌려 버리는 것입니다.
일관성(Consistency)

일관성(Consistency)는 "트랜잭션이 정해진 규칙(Invariant)을 깨지 않는다"로 이해할 수 있습니다. 예를들어 은행의 총 잔고가 1000만원이라고 가정하면은, 어떤 트랜잭션이 내부에서 일어나더라도 개인 잔고의 총 합이 항상 1000만원을 유지해야합니다.
만약에 이러한 원칙이 깨진다면 해당 트랜잭션을 Rollback하게 됩니다.
Java/Spring 코드로는 아래처럼 만들 수 있습니다.
@Transactional
public void transfer(Long fromId, Long toId, Long amount) {
// 1. 계좌 출금
Account fromAccount = accountRepository.findById(fromId).orElseThrow();
fromAccount.withdraw(amount);
// Invariant 체크
if (fromAccount.getBalance() < 0) {
// 잔고가 마이너스가 되면 Invariant가 깨지므로 예외를 던짐!
throw new IllegalArgumentException("잔고가 부족합니다.");
}
// 2. B 계좌 입금
Account toAccount = accountRepository.findById(toId).orElseThrow();
toAccount.deposit(amount);
}
격리성(Isolation)

격리성(Isolation)은 "모든 트랜잭션이 독립적으로 수행되는 것"을 말합니다. 데이터베이스 종류에 따라 멀티스레딩(Multithreading)을 지원하기도 하고 싱글 스레드(Single thread)로만 동작하기도 하지만, 공통점은 여러 개의 트랜잭션이 동시에 데이터베이스에 접근하여 요청을 처리할 수 있다는 점입니다.
이로 인해 특정 데이터에 대한 경쟁 상태(Race Condition)가 발생할 수 있으며, 결과적으로 Phantom Read나 Write Skew 같은 예기치 않은 동시성 오류가 생길 수 있습니다. 데이터베이스는 이러한 오류를 막기 위해서 격리성이라는 특성을 보장합니다.
지속성(Durability)

마지막으로 지속성(Durability)은 "트랜잭션이 성공적으로 커밋(Commit)되면, 영구적으로 데이터베이스에 저장된다"는 것을 의미합니다.
트랜잭션 내에서 데이터를 추가, 수정, 삭제하더라도 "Commit"을 호출하지 않으면, 그 변경 사항은 임시 상태로 남게 됩니다. 만약 이 과정에서 에러가 발생하거나 시스템이 다운되면 데이터베이스는 Rollback이 되기 때문에, 최종 데이터 상태에는 아무런 영향을 주지 않게 됩니다.
아래 코드를 보면 어떻게 COMMIT을 호출하는지 참고 할 수 있습니다.
-- 트랜잭션 시작
BEGIN TRANSACTION;
UPDATE Accounts
SET Balance = Balance - 150
WHERE AccountID = 'A';
UPDATE Accounts
SET Balance = Balance + 150
WHERE AccountID = 'B';
-- 이 Commit을 꼭 호출해야 합니다.
COMMIT;
다음 포스트에서는 ACID의 특성을 유지하기 위해서 어떤 방법을 사용할 수 있는지 더 알아보겠습니다:D
'시스템 디자인 > 데이터베이스' 카테고리의 다른 글
| DB 격리 수준(Isolation Level): Read Committed (0) | 2026.06.14 |
|---|---|
| 인덱싱(Indexing)은 DB를 어떻게 바꿀까? (0) | 2026.06.03 |