IT 개발 라이프/DB

데이터베이스 트랜잭션(Transaction)

10Biliion 2024. 12. 31. 10:19

🧐 트랜잭션이란?

트랜잭션은 데이터베이스에서 하나의 논리적 작업 단위를 뜻합니다. 여러 데이터베이스 연산(INSERT, UPDATE, DELETE 등)을 하나로 묶어서 실행하며, 모든 연산이 성공적으로 완료되거나, 전부 취소(ROLLBACK)되는 것이 보장됩니다.

트랜잭션은 데이터 무결성과 일관성을 유지하기 위한 필수적인 메커니즘입니다.

📋 트랜잭션의 특징 (ACID)

  1. Atomicity (원자성): 트랜잭션 내의 모든 작업이 성공적으로 완료되거나, 전부 취소됩니다.
  2. Consistency (일관성): 트랜잭션이 완료되면 데이터베이스는 항상 일관된 상태를 유지합니다.
  3. Isolation (격리성): 하나의 트랜잭션이 실행되는 동안 다른 트랜잭션이 간섭하지 못합니다.
  4. Durability (지속성): 트랜잭션이 성공적으로 완료되면 결과가 영구적으로 반영됩니다.

✏️ 트랜잭션의 동작 원리

트랜잭션은 주로 다음과 같은 단계를 거쳐 실행됩니다:

  1. BEGIN: 트랜잭션 시작.
  2. 작업 수행: SQL 명령 실행 (INSERT, UPDATE, DELETE 등).
  3. COMMIT: 모든 작업을 성공적으로 완료하고 변경 사항을 데이터베이스에 영구적으로 반영.
  4. ROLLBACK: 오류가 발생하거나 작업을 취소할 때, 모든 변경 사항을 원래 상태로 되돌림.

📖 예제 코드

BEGIN;

-- 데이터 삽입
INSERT INTO accounts (id, balance) VALUES (1, 1000);
INSERT INTO accounts (id, balance) VALUES (2, 2000);

-- 변경 사항 반영
COMMIT;

오류 발생 시:

BEGIN;

-- 데이터 삽입
INSERT INTO accounts (id, balance) VALUES (1, 1000);
INSERT INTO accounts (id, balance) VALUES (2, 'INVALID'); -- 오류 발생

-- 변경 사항 취소
ROLLBACK;

🔍 트랜잭션 격리 수준

데이터베이스에서 트랜잭션은 동시에 실행될 수 있습니다. 이때, 트랜잭션 간의 간섭을 최소화하기 위해 **격리 수준(Isolation Level)**을 설정합니다. 격리 수준은 아래와 같습니다:

  1. Read Uncommitted: 다른 트랜잭션의 미완료 데이터를 읽을 수 있음.
  2. Read Committed: 다른 트랜잭션이 완료된 데이터만 읽을 수 있음.
  3. Repeatable Read: 트랜잭션 동안 동일한 데이터를 읽을 때 결과가 항상 동일.
  4. Serializable: 가장 높은 격리 수준으로, 트랜잭션이 순차적으로 실행됨.

📊 격리 수준 비교표

격리 수준 Dirty Read Non-Repeatable ReadPhantom Read
Read Uncommitted 가능 가능 가능
Read Committed 불가능 가능 가능
Repeatable Read 불가능 불가능 가능
Serializable 불가능 불가능 불가능

🛠️ 트랜잭션 관리 방법

1️⃣ 자동 커밋 (Auto-commit)

대부분의 데이터베이스는 기본적으로 Auto-commit 모드를 사용합니다. 이 모드에서는 각 SQL 명령이 실행될 때마다 자동으로 커밋됩니다. Auto-commit을 끄려면 명시적으로 설정해야 합니다:

SET autocommit = OFF;

2️⃣ 수동 트랜잭션 관리

수동으로 트랜잭션을 시작하고, 필요 시 커밋 또는 롤백을 수행합니다:

BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
COMMIT;

🤔 트랜잭션 사용 시 주의할 점

  1. 잠금(Lock): 트랜잭션이 자원을 점유하는 동안 다른 트랜잭션이 대기할 수 있습니다. 이로 인해 성능 저하나 교착 상태(Deadlock)가 발생할 수 있습니다.
  2. 격리 수준 선택: 성능과 데이터 일관성 간의 균형을 고려해야 합니다.
  3. 트랜잭션 길이: 트랜잭션이 길어질수록 잠금 시간이 늘어나 성능 문제가 발생할 수 있습니다.