기억을 지배하는 기록

데이터베이스 트랜젝션(Transactoin) - ACID (Isolation) 본문

Database Learning Guide

데이터베이스 트랜젝션(Transactoin) - ACID (Isolation)

Andrew's Akashic Records 2024. 11. 20. 11:21
728x90

데이터베이스에서 트랜잭션(Transaction)은 데이터베이스의 상태를 변화시키는 작업의 논리적인 단위입니다. 일반적으로 트랜잭션은 여러 작업을 하나로 묶어 데이터의 일관성을 보장하는 역할을 합니다. 트랜잭션의 가장 큰 특징은 모든 작업이 성공적으로 완료되거나, 그렇지 않을 경우 모두 원래대로 복구되어야 한다는 점입니다. 이 원칙은 데이터베이스의 무결성과 일관성을 유지하는 데 중요합니다.

트랜잭션에는 보통 다음과 같은 4가지 성질이 있습니다. 이를 ACID라고 합니다:

1. Atomicity (원자성)

데이터베이스 트랜젝션(Transactoin) - ACID (Atomicity)

2. Consistency (일관성)

데이터베이스 트랜젝션(Transactoin) - ACID (Consistency)

3. Isolation(격리성)

데이터베이스의 트랜잭션(Transaction)에서 격리성(Isolation)여러 트랜잭션이 동시에 수행될 때 각 트랜잭션이 서로의 중간 결과에 영향을 받지 않고 독립적으로 수행될 수 있도록 보장하는 특성을 의미합니다. 격리성은 데이터베이스의 일관성을 유지하면서 동시에 여러 작업을 안전하게 처리할 수 있게 하는 중요한 요소입니다.

격리성의 주요 개념

  1. 동시성 제어(Concurrency Control):
    • 데이터베이스는 여러 사용자가 동시에 트랜잭션을 실행할 수 있는 환경을 제공합니다. 이때 각 트랜잭션이 독립적으로 실행되도록 보장하는 것이 격리성의 목표입니다.
    • 격리성은 동시성 제어 메커니즘을 통해 구현되며, 이를 통해 각 트랜잭션이 다른 트랜잭션의 중간 결과를 볼 수 없도록 막아 데이터의 무결성과 일관성을 유지합니다.
  2. 트랜잭션 격리 수준(Transaction Isolation Levels):
    • 격리성의 정도는 격리 수준(Isolation Level)을 통해 조절할 수 있습니다. 격리 수준은 동시성(성능)과 일관성 간의 균형을 조정하는 중요한 역할을 합니다.
    • 트랜잭션의 격리 수준이 높을수록 다른 트랜잭션의 영향을 받지 않지만, 동시에 성능이 저하될 수 있습니다. 반대로 격리 수준이 낮을수록 성능은 향상되지만, 데이터 일관성 문제가 발생할 가능성이 커집니다.

트랜잭션 격리 수준 (Isolation Levels)

격리성은 네 가지 표준 격리 수준을 통해 조절됩니다. 각 격리 수준은 데이터의 일관성동시성 간의 절충점을 제공합니다.

  1. Read Uncommitted (가장 낮은 격리 수준)
    • 트랜잭션이 커밋되지 않은 데이터를 다른 트랜잭션이 읽을 수 있음을 의미합니다. 이는 가장 낮은 수준의 격리성을 제공하며, 동시성은 높지만 데이터 일관성 문제가 발생할 수 있습니다.
    • 문제점:
      • 더티 리드(Dirty Read): 다른 트랜잭션이 아직 커밋되지 않은 데이터를 읽을 수 있기 때문에, 그 데이터가 나중에 롤백되면 잘못된 데이터를 읽게 되는 문제가 발생할 수 있습니다.
  2. Read Committed (기본 격리 수준)
    • 다른 트랜잭션이 커밋한 데이터만 읽을 수 있음을 의미합니다. 대부분의 데이터베이스에서 기본으로 설정된 격리 수준입니다.
    • 문제점:
      • 비반복적 읽기(Non-Repeatable Read): 동일한 쿼리를 반복해서 실행했을 때, 다른 트랜잭션이 데이터를 수정하고 커밋하면 이전에 읽은 데이터와 다른 결과가 반환될 수 있습니다.
  3. Repeatable Read
    • 한 번 트랜잭션에서 읽은 데이터를 다른 트랜잭션이 변경할 수 없도록 보장합니다. 트랜잭션 중 동일한 데이터를 여러 번 읽어도 결과가 항상 동일하게 유지됩니다.
    • 문제점:
      • 팬텀 리드(Phantom Read): 반복 쿼리에서 레코드의 개수가 달라질 수 있는 문제가 있습니다. 예를 들어, 다른 트랜잭션이 새로운 레코드를 삽입하면, 트랜잭션 내에서 재실행된 쿼리에서 추가된 레코드를 볼 수 있습니다.
  4. Serializable (가장 높은 격리 수준)
    • 모든 트랜잭션을 직렬화하여 실행하는 것처럼 보이게 합니다. 즉, 동시에 실행되는 트랜잭션이 없도록 트랜잭션을 순차적으로 처리하여 완벽한 일관성을 보장합니다.
    • 문제점:
      • 성능 저하: 트랜잭션을 직렬화하여 처리하기 때문에 동시성 측면에서 성능이 많이 저하될 수 있습니다.
    • 장점: 데이터의 일관성을 최대로 보장하며, 팬텀 리드비반복적 읽기와 같은 문제가 발생하지 않습니다.

격리성 문제 (Isolation Issues)

격리성이 낮거나 트랜잭션이 적절히 관리되지 않을 경우 다음과 같은 문제들이 발생할 수 있습니다:

  1. Dirty Read (더티 리드):
    • 다른 트랜잭션이 아직 커밋되지 않은 데이터를 읽는 경우입니다. 이후에 해당 트랜잭션이 롤백되면 잘못된 데이터를 읽은 셈이 됩니다.
    • 예시: 트랜잭션 A가 계좌에서 100달러를 출금했지만 아직 커밋되지 않았을 때, 트랜잭션 B가 이 출금된 상태의 계좌를 읽게 되면 나중에 트랜잭션 A가 롤백될 경우 트랜잭션 B는 잘못된 정보를 기반으로 작업하게 됩니다.
  2. Non-Repeatable Read (비반복적 읽기):
    • 동일한 쿼리를 반복해서 실행할 때 다른 결과가 반환되는 경우입니다. 이는 다른 트랜잭션이 데이터를 변경하거나 삭제했기 때문에 발생합니다.
    • 예시: 트랜잭션 A가 계좌의 잔액을 읽고 있는 동안, 트랜잭션 B가 해당 계좌의 잔액을 수정한 후 커밋하면, 트랜잭션 A가 동일한 계좌를 다시 읽을 때 다른 결과를 볼 수 있습니다.
  3. Phantom Read (팬텀 리드):
    • 동일한 쿼리를 반복해서 실행했을 때, 레코드의 개수가 달라지는 경우입니다. 이는 다른 트랜잭션이 새로운 레코드를 삽입하거나 삭제했기 때문에 발생합니다.
    • 예시: 트랜잭션 A가 특정 조건을 만족하는 레코드를 조회했을 때, 이후 트랜잭션 B가 새로운 레코드를 삽입하여 동일한 조건을 만족하면, 트랜잭션 A가 쿼리를 다시 실행할 때 추가된 레코드를 볼 수 있습니다.
    • 이 방식은 읽기 작업이 많은 경우 유리하며, 트랜잭션 간의 잠금 경합을 줄일 수 있습니다.

트랜잭션 격리성과 성능의 균형

  • 격리성은 데이터베이스의 일관성을 유지하는 데 중요하지만, 높은 격리 수준은 동시성(성능)을 떨어뜨릴 수 있습니다.
  • 예를 들어, Serializable 격리 수준은 가장 높은 일관성을 보장하지만, 성능이 저하될 가능성이 큽니다. 반면, Read Uncommitted는 성능은 좋지만, 데이터 일관성 문제가 발생할 가능성이 큽니다.
  • 데이터베이스 관리자는 어플리케이션의 특성에 맞는 적절한 격리 수준을 설정하여 일관성과 성능 간의 균형을 유지해야 합니다.
728x90

데이터베이스별 트랜잭션 격리 수준 지정방법

각 데이터베이스 관리 시스템(DBMS)은 트랜잭션 격리 수준(Isolation Level)을 설정할 수 있는 기능을 제공합니다. 이를 통해 동시성(성능)과 일관성 간의 균형을 조절할 수 있습니다. 주요 데이터베이스 시스템인 Oracle, MySQL, 그리고 PostgreSQL에서 트랜잭션 격리 수준을 지정하는 방법을 설명하겠습니다.

 

1. Oracle Database의 트랜잭션 격리 수준 설정

Oracle은 기본적으로 트랜잭션 격리 수준이 Read Committed로 설정되어 있으며, 필요에 따라 Serializable 수준을 설정할 수 있습니다.

  • 세션 단위로 트랜잭션 격리 수준 지정:
    • Oracle에서는 트랜잭션의 격리 수준을 세션 단위로 설정할 수 있으며, SET TRANSACTION 명령어를 사용합니다.
    • Read Committed (기본 설정):
      SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
    • Serializable:
      SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
    • 이 명령어는 현재 세션에서 실행되는 다음 트랜잭션에만 적용됩니다.
  • 주의 사항:
    • Oracle은 MVCC를 사용해 트랜잭션의 일관성을 유지합니다. 기본 격리 수준인 Read Committed는 대부분의 어플리케이션에서 충분히 높은 동시성과 일관성을 제공합니다.
    • Serializable 수준에서는 트랜잭션 간의 충돌을 최소화하기 위해 데이터베이스가 높은 수준의 잠금을 사용하므로, 성능에 영향을 줄 수 있습니다.

2. MySQL의 트랜잭션 격리 수준 설정

MySQL은 기본적으로 Repeatable Read를 격리 수준으로 사용하며, 필요에 따라 다른 격리 수준을 설정할 수 있습니다. MySQL에서는 주로 InnoDB 스토리지 엔진을 사용하여 트랜잭션을 관리합니다.

  • 글로벌, 세션, 트랜잭션 단위 격리 수준 지정:
    • MySQL에서는 격리 수준을 글로벌, 세션, 또는 트랜잭션 단위로 설정할 수 있습니다.
    • 글로벌 격리 수준 설정 (서버 전체 적용):
      SET GLOBAL TRANSACTION ISOLATION LEVEL [LEVEL];
      예:
      SET GLOBAL TRANSACTION ISOLATION LEVEL REPEATABLE READ;
    • 세션 격리 수준 설정 (현재 세션에만 적용):
      SET SESSION TRANSACTION ISOLATION LEVEL [LEVEL];
      예:
      SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
    • 트랜잭션 단위 격리 수준 설정 (특정 트랜잭션에만 적용):
      SET TRANSACTION ISOLATION LEVEL [LEVEL];
      예:
      SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
  • 지원되는 격리 수준:
    • READ UNCOMMITTED: 가장 낮은 격리 수준으로 더티 리드가 가능.
    • READ COMMITTED: 커밋된 데이터만 읽을 수 있도록 보장.
    • REPEATABLE READ: 동일 트랜잭션 내에서 동일한 쿼리에 대해 일관된 결과 제공.
    • SERIALIZABLE: 트랜잭션을 직렬화하여 실행하는 것처럼 보이도록 처리.

3. PostgreSQL의 트랜잭션 격리 수준 설정

PostgreSQL은 기본적으로 Read Committed 격리 수준을 사용하며, 필요에 따라 격리 수준을 변경할 수 있습니다. PostgreSQL은 또한 MVCC를 사용하여 일관성을 유지합니다.

  • 트랜잭션 단위 격리 수준 설정:
    • PostgreSQL에서 트랜잭션의 격리 수준을 설정하기 위해 SET TRANSACTION 명령어를 사용합니다.
    • Read Committed (기본 설정):
      SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
    • Repeatable Read:
      SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
    • Serializable:
      SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
    • 이 명령어는 현재 실행 중인 트랜잭션에만 적용됩니다.
  • 세션 단위 격리 수준 설정:
    • 특정 세션에 대해서는 다음과 같이 격리 수준을 설정할 수 있습니다.
      SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL [LEVEL];
      예:
      SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL REPEATABLE READ;
  • 지원되는 격리 수준:
    • READ UNCOMMITTED: PostgreSQL에서는 공식적으로 지원하지 않습니다. 대신 READ COMMITTED가 가장 낮은 수준입니다.
    • READ COMMITTED: 커밋된 데이터만 읽도록 보장하며, 기본 격리 수준입니다.
    • REPEATABLE READ: 동일 트랜잭션 내에서 동일한 쿼리에 대해 일관된 결과를 보장합니다.
    • SERIALIZABLE: 트랜잭션을 직렬화하여 처리하며, 가장 높은 수준의 격리성을 제공합니다.

프로그래밍 레벨에서 트랜잭션 격리 수준 지정방법

프로그래밍 환경에서 트랜잭션 격리 수준(Isolation Level)을 설정하는 방법은 사용되는 프로그래밍 언어와 데이터베이스 라이브러리 또는 프레임워크에 따라 다릅니다. 여기에서는 Java (JDBC), Python (SQLAlchemy와 psycopg2), 그리고 Spring Framework에서 트랜잭션 격리 수준을 설정하는 방법을 설명하겠습니다.

 

1. Java (JDBC)에서 트랜잭션 격리 수준 설정

Java에서 JDBC를 통해 데이터베이스에 연결할 때, 트랜잭션 격리 수준은 Connection 객체를 사용하여 설정할 수 있습니다. JDBC는 다음과 같은 격리 수준을 제공합니다:

  • TRANSACTION_READ_UNCOMMITTED
  • TRANSACTION_READ_COMMITTED
  • TRANSACTION_REPEATABLE_READ
  • TRANSACTION_SERIALIZABLE

예시 코드

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class TransactionIsolationExample {
    public static void main(String[] args) {
        String url = "jdbc:mysql://localhost:3306/mydatabase";
        String user = "username";
        String password = "password";

        try (Connection connection = DriverManager.getConnection(url, user, password)) {
            // 트랜잭션 격리 수준 설정 (예: REPEATABLE READ)
            connection.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);

            // 자동 커밋 비활성화
            connection.setAutoCommit(false);

            // 여기서 데이터베이스 작업 수행
            // ...

            // 트랜잭션 커밋
            connection.commit();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}
  • setTransactionIsolation(int level): 트랜잭션의 격리 수준을 설정하는 메소드입니다.
  • setAutoCommit(false): 트랜잭션 제어를 위해 자동 커밋을 비활성화합니다.

2. Python (SQLAlchemy와 psycopg2)에서 트랜잭션 격리 수준 설정

Python에서 데이터베이스 연결에 SQLAlchemy 또는 psycopg2와 같은 라이브러리를 사용할 수 있습니다. 이들 라이브러리에서 트랜잭션 격리 수준을 설정하는 방법을 설명합니다.

 

2.1. SQLAlchemy에서 트랜잭션 격리 수준 설정

SQLAlchemysession 또는 engine 객체를 통해 트랜잭션 격리 수준을 설정할 수 있습니다.

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

# 데이터베이스 엔진 생성 (예: PostgreSQL)
engine = create_engine('postgresql://username:password@localhost/mydatabase')

# 세션 팩토리 생성
Session = sessionmaker(bind=engine)

# 격리 수준을 SERIALIZABLE로 설정하여 세션 생성
session = Session(bind=engine.execution_options(isolation_level="SERIALIZABLE"))

try:
    # 데이터 작업 수행
    # ...

    # 트랜잭션 커밋
    session.commit()
except:
    # 오류 발생 시 롤백
    session.rollback()
finally:
    # 세션 종료
    session.close()
  • execution_options(isolation_level="SERIALIZABLE"): 세션의 트랜잭션 격리 수준을 설정하는 옵션입니다.
  • 지원되는 격리 수준은 "READ UNCOMMITTED", "READ COMMITTED", "REPEATABLE READ", "SERIALIZABLE" 등이 있습니다.

2.2. psycopg2에서 트랜잭션 격리 수준 설정

psycopg2PostgreSQL 데이터베이스와의 연결을 관리하며, 트랜잭션 격리 수준을 직접 설정할 수 있습니다.

import psycopg2
from psycopg2 import sql

# 데이터베이스 연결
conn = psycopg2.connect(
    dbname="mydatabase",
    user="username",
    password="password",
    host="localhost"
)

# 커서 생성
cur = conn.cursor()

# 트랜잭션 격리 수준 설정 (예: REPEATABLE READ)
conn.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_REPEATABLE_READ)

try:
    # 데이터 작업 수행
    # ...

    # 트랜잭션 커밋
    conn.commit()
except Exception as e:
    # 오류 발생 시 롤백
    conn.rollback()
    print(f"Error: {e}")
finally:
    # 커서 및 연결 종료
    cur.close()
    conn.close()
  • set_isolation_level(): 트랜잭션 격리 수준을 설정하는 메소드입니다.
  • 격리 수준 상수: ISOLATION_LEVEL_READ_COMMITTED, ISOLATION_LEVEL_REPEATABLE_READ, ISOLATION_LEVEL_SERIALIZABLE 등이 있습니다.

3. Spring Framework에서 트랜잭션 격리 수준 설정

Spring FrameworkSpring Data JPASpring JDBC에서 @Transactional 애노테이션을 사용하여 트랜잭션 격리 수준을 지정할 수 있습니다.

예시 코드 (Spring Data JPA)

import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.stereotype.Service;

@Service
public class MyService {

    @Transactional(isolation = Isolation.REPEATABLE_READ)
    public void performTransaction() {
        // 데이터 작업 수행
    }
}
  • @Transactional(isolation = Isolation.REPEATABLE_READ): 메소드나 클래스 수준에서 트랜잭션 격리 수준을 설정합니다.
  • Spring의 격리 수준은 다음과 같습니다:
    • Isolation.DEFAULT: 기본 설정 (데이터베이스에 따라 다름)
    • Isolation.READ_UNCOMMITTED
    • Isolation.READ_COMMITTED
    • Isolation.REPEATABLE_READ
    • Isolation.SERIALIZABLE

4. Durability(지속성)

데이터베이스 트랜젝션(Transactoin) - ACID (Durability)

Database Transaction

728x90
Comments