트랜젝션 (Transaction)
트랜잭션은 데이터베이스 작업의 논리적인 작업 단위를 말합니다. 테이블 내용을 변경하는 여러 개의 데이터 조작(INSERT, UPDATE, DELETE 등)이 하나의 트랜잭션으로 묶여 처리되며, 작업이 성공적으로 완료되거나 실패할 경우 데이터베이스의 상태를 일관되게 유지하도록 보장합니다.
- 쉽게 말하자면 :
- 트랜잭션은 여러 작업을 하나로 묶어 "전부 성공" 또는 "전부 실패"로 처리합니다.
- ex. 은행 송금에서 "출금"과 "입금"은 반드시 함께 성공하거나 함께 실패해야 합니다.
특징
트랜잭션은 데이터 무결성을 보장하기 위해 다음 네 가지 속성(ACID)을 충족해야 합니다.
1. 원자성 (Atomicity)
- 정의 : 트랜잭션 내의 모든 작업은 하나의 단위로 실행되며, 모두 성공하거나 전혀 실행되지 않아야 합니다.
- 중요성 : 작업 도중 오류가 발생하면 데이터베이스는 변경 이전 상태로 복구됩니다.
- ex. 은행에서 A 계좌에서 100원을 출금하고 B 계좌에 100원을 입금하는 경우, 출금만 성공하고 입금이 실패하면 데이터 불일치가 발생할 수 있습니다. 트랜잭션은 이를 방지합니다.
2. 일관성 (Consistency)
- 정의 : 트랜잭션이 성공적으로 완료되면 데이터베이스는 항상 일관된 상태를 유지해야 합니다.
- 중요성 : 데이터베이스가 정의된 규칙(제약 조건)을 항상 만족하도록 보장합니다.
- ex. 은행 계좌의 잔액은 음수가 될 수 없습니다. 트랜잭션은 이러한 규칙이 깨지지 않도록 처리합니다.
3. 고립성 (Isolation)
- 정의 : 동시에 실행되는 여러 트랜잭션이 서로 간섭하지 않도록 보장합니다.
- 중요성 : 트랜잭션 간의 간섭이 없으므로 독립적으로 실행된 것처럼 보입니다.
- ex. 한 사용자가 계좌 잔액을 조회하는 중에 다른 사용자가 잔액을 변경해도 조회 결과는 일관성을 유지해야 합니다.
4. 내구성 (Durability)
- 정의 : 트랜잭션이 성공적으로 완료되면 그 결과는 영구적으로 데이터베이스에 반영됩니다.
- 중요성 : 시스템 장애가 발생해도 트랜잭션 결과가 손실되지 않습니다.
- ex. 은행 이체가 완료된 후 서버가 다운되더라도 이체 결과는 데이터베이스에 유지됩니다.
중요성
1. 데이터 무결성 보장
트랜잭션은 데이터를 일관된 상태로 유지하여 데이터의 신뢰성을 보장합니다.
2. 장애 복구
작업 도중 오류가 발생해도 데이터가 손상되지 않도록 원래 상태로 복구할 수 있습니다.
3. 동시성 제어
여러 사용자가 동시에 데이터베이스에 접근해도 데이터가 충돌하지 않도록 관리합니다.
4. 비즈니스 로직 구현
은행 송금, 재고 관리 등 비즈니스 로직에서 복잡한 데이터 변경을 안전하게 처리할 수 있습니다.
과정
시작 → 작업 실행 → 커밋 또는 롤백
1. 트랜잭션 시작 : 트랜잭션이 열리며 데이터베이스 작업이 시작됩니다.
2. 작업 실행 : 데이터베이스에 데이터를 삽입, 수정, 삭제하는 작업이 수행됩니다.
3. 커밋 (Commit) : 트랜잭션 내의 모든 작업이 성공적으로 완료되면 데이터베이스에 작업 결과를 반영합니다.
4. 롤백 (Rollback) : 트랜잭션 내의 작업 중 하나라도 실패하면, 모든 작업을 취소하고 데이터베이스를 원래 상태로 복구합니다.
SQL 예시
1. 계좌 이체
START TRANSACTION;
-- 송금하는 계좌에서 금액 차감
UPDATE bank_accounts
SET balance = balance - 100000
WHERE account_id = 'A001';
-- 받는 계좌로 금액 추가
UPDATE bank_accounts
SET balance = balance + 100000
WHERE account_id = 'B001';
-- 거래 내역 기록
INSERT INTO transactions
(from_account, to_account, amount, transaction_date)
VALUES ('A001', 'B001', 100000, NOW());
COMMIT;
2. 재고 관리
START TRANSACTION;
-- 재고 확인
SELECT @current_stock := stock
FROM products
WHERE product_id = 1234
FOR UPDATE; -- 행 잠금
IF @current_stock >= 3 THEN
-- 재고 감소
UPDATE products
SET stock = stock - 3
WHERE product_id = 1234;
-- 주문 생성
INSERT INTO orders
(order_id, product_id, quantity, order_date)
VALUES (UUID(), 1234, 3, NOW());
COMMIT;
ELSE
ROLLBACK;
END IF;
Java 예시
1. 은행 송금
A 계좌에서 B 계좌로 송금할 때, 출금과 입금은 하나의 트랜잭션으로 처리됩니다.
@Transactional
public void transferMoney(Account fromAccount, Account toAccount, double amount) {
fromAccount.debit(amount); // 출금
toAccount.credit(amount); // 입금
if (amount > 1000) {
throw new RuntimeException("Transfer limit exceeded");
}
}
- 트랜잭션 처리 과정 : 출금과 입금 작업이 실행됩니다. → 모든 작업이 성공하면 커밋됩니다. → 도중에 오류가 발생하면 롤백됩니다.
2. 온라인 쇼핑몰 주문
주문, 재고 차감, 결제는 하나의 트랜잭션으로 묶여야 합니다.
@Transactional
public void placeOrder(Order order) {
orderRepository.save(order); // 주문 생성
inventoryService.reduceStock(order); // 재고 차감
paymentService.processPayment(order); // 결제 처리
}
트랜잭션 관리 방법
1. 수동 (JDBC 기반)
Connection conn = dataSource.getConnection();
try {
conn.setAutoCommit(false); // 자동 커밋 비활성화
// 데이터베이스 작업 수행
String sql1 = "INSERT INTO table1 ...";
PreparedStatement stmt1 = conn.prepareStatement(sql1);
stmt1.executeUpdate();
String sql2 = "UPDATE table2 ...";
PreparedStatement stmt2 = conn.prepareStatement(sql2);
stmt2.executeUpdate();
conn.commit(); // 성공 시 커밋
} catch (Exception e) {
conn.rollback(); // 실패 시 롤백
} finally {
conn.close(); // 연결 닫기
}
2. Spring Framework @Transactional
@Service
public class MyService {
@Transactional
public void performDatabaseOperations() {
// 데이터베이스 작업 수행
myRepository.save(entity1);
myRepository.update(entity2);
// 예외 발생 시 트랜잭션은 자동 롤백됨
}
}
- Spring의 AOP(Aspect-Oriented Programming)와 프록시(Proxy)를 사용한 선언적 트랜잭션 관리
- @Transactional 애노테이션을 사용하여 메서드나 클래스 단위에서 트랜잭션 경계를 정의
3. SQL
START TRANSACTION;
-- 데이터베이스 작업 수행
INSERT INTO table1 (...) VALUES (...);
UPDATE table2 SET ...;
-- 성공 시 커밋
COMMIT;
-- 실패 시 롤백
ROLLBACK;
- 데이터베이스 자체에서 트랜잭션 경계를 명시
- SQL 명령어를 사용하여 트랜잭션을 시작(START TRANSACTION), 커밋(COMMIT), 롤백(ROLLBACK) 처리
주의
- 트랜잭션 범위 : 트랜잭션이 너무 길면 성능에 영향을 미칠 수 있으므로 필요한 최소 범위로 설정합니다.
- 트랜잭션 격리 수준 : 데이터 충돌 방지를 위해 격리 수준을 적절히 설정합니다. 기본값은 READ COMMITTED입니다.
- 롤백 조건 : Spring에서는 기본적으로 RuntimeException이 발생할 때만 롤백됩니다. 특정 예외에서도 롤백하려면 rollbackFor 옵션을 설정해야 합니다.
출처
OpenAI의 ChatGPT (https://openai.com)
'DB > MySQL' 카테고리의 다른 글
| DELETE vs TRUNCATE (0) | 2025.02.26 |
|---|---|
| 서브쿼리(Subquery) (0) | 2025.01.06 |
| GROUP_CONCAT feat. DISTINCT (0) | 2025.01.03 |
| GROUP BY (0) | 2025.01.02 |
| JOIN (2) | 2025.01.01 |