코드의 여백

[데이터베이스] 트랜잭션(Transaction)은 왜 필요한가?

by rowing0328

Intro

현대의 데이터베이스는 수많은 사용자의 동시 요청과 예기치 않은 오류 상황에서도 데이터의

일관성과 무결성을 유지해야 한다. 이를 가능하게 하는 핵심 개념이 바로 트랜잭션이다.

 

이번 포스트에서는 트랜잭션이 무엇인지, 왜 필요하지부터 시작해, 트랜잭션의 동작 원리와

다양한 사용 시나리오, 그리고 DBMS별 처리 방식의 차이까지 폭넓게 살펴보겠다.

 

 

트랜잭션이란 무엇이며 왜 필요한가?

트랜잭션이은 데이터베이스에서 한 번에 수행되어야 할 일련의 작업을 하나의 논리적 단위로 묶은 것이다.
이 작업들은 모두 성공하거나, 하나라도 실패하면 전체를 취소(rollback)해 이전 상태로 되돌린다.

 

즉, "모두 되거나 아니면 전혀 안되거나"의 원칙이 적용되며, 중간 결과만 저장되는 일은 없다.

 

트랜잭션이 수행되는 동안 일시적으로 데이터 상태가 모순될 수 있어도,
트랜잭션이 끝나 커밋(commit)될 때는 일관된 결과만 데이터베이스에 반영된다.

 

트랜잭션은 장애나 오류 발생 시에도 데이터의 무결성을 보장한다. 커밋된 트랜잭션만 유지되고,
진행 중이던 트랜잭션은 모두 롤백되므로 장애 복구 후에도 데이터베이스는 일관된 상태를 유지한다.

 

또한 여러 사용자가 동시에 같은 데이터를 사용하는 병행 처리 상황에서도,
트랜잭션은 각 작업 단위를 격리해 충돌이나 불일치를 방지한다.

 

결국 트랜잭션은 원자성(Atomicity), 일관성(Consistency), 고립성(Isolation), 지속성

(Durability)이라는 ACID 특성을 통해 데이터베이스의 안정성과 신뢰성을 지켜준다.

 

 

여러 SQL 쿼리를 하나의 단위로 묶는 이유

트랜잭션의 핵심은 여러 SQL 쿼리를 하나의 작업 단위로 묶는 것이다. 이유는 간단하다.

서로 관련된 여러 쿼리 중 일부만 성공하면 데이터 불일치가 발생할 수 있기 때문이다.

 

트랜잭션으로 묶으면 모든 쿼리가 성공해야 커밋되고,

하나라도 실패하면 이전의 모든 작업이 되돌려진다. 이 덕분에 데이터 정합성이 보장된다.

 

예를 들어, A 테이블에서 값을 읽고 B 테이블에 반영하는 두 개의 쿼리가 있다면,
둘 중 하나만 성공하면 데이터베이스는 모순 상태에 빠지게 된다.

 

트랜잭션으로 묶으면 둘 중 하나라도 실패 시 전체 작업이 롤백된다.

 

 

계좌 이체로 보는 트랜잭션

트랜잭션을 이해하는 데 가장 흔한 예시는 계좌 이체이다.

 

예: 계좌 A에서 B로 100원을 송금하는 작업은 아래 두 단계로 구성된다:

  • 계좌 A의 잔액에서 100원 감소
  • 계좌 B의 잔액에 100원 증가

 

이 두 단계는 모두 완료되어야 의미가 있습니다. 중간에 오류가 발생해 A에서 돈은 빠졌는데

B에 입금되지 않으면, 심각한 문제가 된다.

 

트랜잭션을 사용하면 아래처럼 처리된다:

BEGIN;

UPDATE accounts
SET balance = balance - 100
WHERE account_id = 'A';

UPDATE accounts
SET balance = balance + 100
WHERE account_id = 'B';

COMMIT;

 

중간에 실패하면 ROLLBACK을 호출하여 A 계좌도 원래대로 복구된다.

 

 

트랜잭션의 수명주기

트랜잭션은 시작부터 종료까지 다음의 단계를 거친다:

  • BEGIN
    트랜잭션 시작. 이후의 쿼리들이 이 트랜잭션에 포함된다.
  • COMMIT
    변경사항을 확정. 영구 반영되며, 이후에는 롤백할 수 없다.
  • ROLLBACK
    커밋 전까지의 변경을 모두 취소. 트랜잭션 시작 이전 상태로 되돌린다.

 

트랜잭션은 일반적으로 "진행 중 -> 커밋" 또는 "진행 중 -> 롤백" 흐름을 따른다.
중요한건, 커밋 전까지의 변경은 외부에 보이지 않는다는 점이다.

 

트랜잭션 중 데이터는 어떻게 저장될까?

트랜잭션 동안 변경된 데이터는 즉시 디스크에 저장되지 않고,

먼저 메모리나 임시 공간에 보관된다. 이를 부분 커밋 상태(partially committed)라고 한다.

 

COMMIT이 호출되면 메모리에 있던 변경사항이 디스크에 기록된다.

대부분의 DBMS는 Write-Ahead Logging(WAL)을 사용해,
로그에 먼저 기록한 후 실제 데이터를 반영하여 지속성(Durability)을 보장한다.

 

ROLLBACK이 호출되면 이 임시 변경들은 폐기되고, 디스크에는 아무 변화도 남지 않습니다.

 

장애 상황에서의 복구

트랜잭션은 예기치 못한 시스템 장애 시에도 데이터베이스를 보호한다.

  • 장애 이전에 커밋된 트랜잭션 → 재시작 후에도 그대로 유지
  • 장애 당시 진행 중이던 트랜잭션 → 자동 롤백

 

DBMS는 트랜잭션 로그(WAL 등)를 분석해 완료된 작업은 다시(redo)하고,
트랜잭션은 취소(undo)한다.

 

읽기 전용 트랜잭션의 역할

트랜잭션은 데이터 조회에도 유용한다.

SELECT만 수행하는 읽기 전용 트랜잭션(read-only)을 사용할 수 있다.

 

이 경우 트랜잭션 시작 시점의 데이터를 기준으로 조회하므로,
여러 SELECT 사이에 데이터가 바뀌어도 결과는 일관성을 유지한다.

 

SET TRANSACTION READ ONLY;
BEGIN;
-- 여러 SELECT 쿼리 실행
COMMIT;

데이터 수정이 없기 때문에 DBMS는 내부 락을 줄이고, 최적화를 적용할 수 있다.

 

 

무결성과 트랜잭션

데이터베이스는 다양한 무결성 제약 조건(CHECK, UNIQUE, NOT NULL, FOREIGN KEY 등)을 통해 데이터의 정확성을 보장한다.

 

트랜잭션은 이러한 제약을 어겼을 때 전체 작업을 롤백함으로써,
데이터베이스가 항상 유효한 상태로 유지되도록 돕습니다.

 

예를 들어 외래 키 제약을 위반하는 INSERT가 발생하면,
해당 트랜잭션은 즉시 롤백되어 잘못된 데이터가 저장되지 않도록 막습니다.

 

 

명시적 vs 암시적 트랜잭션

트랜잭션 제어 방식은 두 가지이다.

  • 명시적 트랜잭션
    개발자가 BEGIN, COMMIT/ROLLBACK 직접 작성
  • 암시적 트랜잭션 (Autocommit)
    DBMS가 각 쿼리를 자동으로 트랜잭션 단위로 처리하고 즉시 커밋

 

MySQL, PostgreSQL, SQL Server는 기본적으로 Autocommit이다.
단일 INSERT만 해도 자동 커밋된다.

 

SQL Server는 SET IMPLICIT_TRANSACTIONS ON 설정 시 자동 시작 + 수동 커밋도 가능하며,
Oracle은 암시적 트랜잭션이지만 자동 커밋은 하지 않는다.

복잡한 작업에는 명시적 트랜잭션을 사용하는 것이 안전하다.
DDL 문은 일부 DBMS에서 자동 커밋되므로 주의가 필요하다.

 

 

마무리

트랜잭션은 데이버베이스의 신뢰성과 일관성을 유지하는 핵심 도구이다.

 

요약하자면, "트랜잭션으로 묶어라. 함께 성공하고, 문제 생기면 함께 취소하라."
이것이 핵심 원칙이다.

 

ACID 원칙에 기반한 트랜잭션 설계는 애플리케이션의 안정성을 크게 높여준다.

 

트랜잭션 경계를 명확히 설정하고,
적절한 시점에 COMMIT 또는 ROLLBACK을 하도록 하세요.

트랜잭션은 결국 개발자의 실수를 막고,
사용자의 데이터를 지키는 든든한 안전장치이다.

블로그의 정보

코드의 여백

rowing0328

활동하기