ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Transaction은 논리적 작업 단위의 집합이다
    Computer Science/Database 2021. 7. 6. 01:03

    데이터베이스에서 의미하는 트랜잭션이란 데이터베이스 관리 시스템(DBMS) 또는 유사한 시스템(트랜잭션의 성공과 실패가 분명하고 상호 독립적이며 일관되고 신뢰성 있는 시스템)에서의 가장 작은 상호작용 단위를 말한다.

    Transaction: 하나의 논리적 작업 단위를 구성하는 일련의 연산들의 집합

    ex) 계좌 간의 자금 이체
    한 계좌에서 다른 계좌로 10만원을 이체하는 작업은 한 계좌에서 10만원 인출 + 다른 계좌로 10만원 입금의 두 작업으로 구성된다
    하지만 전체 작업이 정상적으로 처리될 수 없는 경우 아무 것도 실행되지 않은 처음 상태로 복구되어야 한다
    따라서 트랜잭션이란 다양한 데이터 항목들을 액세스하고 갱신하는 프로그램 수행의 단위가 된다

    https://github.com/JaeYeopHan/Interview_Question_for_Beginner/raw/master/Database/images/transaction-status.png

    위의 그림은 트랜잭션이 가질 수 있는 상태를 나타낸다

    • Active
      • 트랜잭션의 활동 상태. 트랜잭션이 현재 실행중임을 의미한다
    • Failed
      • 트랜잭션 실패 상태. 트랜잭션이 더 이상 정상적으로 진행할 수 없음을 의미한다
    • Partially Committed
      • 트랜잭션의 Commit 명령이 도착한 상태
      • 트랜잭션의 Commit 이전 SQL 문이 수행되고 Commit만 남은 상태를 의미한다
    • Committed
      • 트랜잭션 완료 상태. 트랜잭션이 정상적으로 수행되었음을 의미한다
      • Commit 요청이 들어오면 Partial Committed 상태가 되고, 이후 Commit을 문제없이 수행할 수 있을 때 Committed 상태로 전이된다
    • Aborted
      • 트랜잭션 취소 상태. 트랜잭션이 취소되고 트랜잭션 실행 이전 데이터로 돌아간 상태를 의미한다

    1. Actomicity (원자성)

    : DBMS는 완료되지 않은 트랜잭션의 중간 상태를 데이터베이스에 반영해서는 안 된다
    ex) 이체 과정 중 트랜잭션이 실패하게 되어 예금이 사라지는 경우 방지
    트랜잭션의 1️⃣모든 연산들이 정상적으로 수행 완료되거나, 2️⃣어떠한 연산도 수행되지 않은 상태를 보장해야 한다.
    이 특성은 'all or nothing' 특성으로 설명된다.

    2. Consistency (일관성)

    : 고립된 트랜잭션의 수행이 데이터베이스의 일관성을 보존해야 한다. 즉, 성공적으로 수행된 트랜잭션은 정당한 데이터들만을 데이터베이스에 반영해야 한다.
    트랜잭션의 수행 = 데이터베이스 상태 간의 전이(transition)
    으로 봤을 때, 트랜잭션 수행 전/후의 데이터베이스 상태는 각각 일관성이 보장되는 서로 다른 상태가 된다.

    3. Isolation (독립성)

    여러 트랜잭션이 동시에 수행되더라도 각각의 트랜잭션은 다른 트랜잭션의 수행에 영향을 받지 않고 독립적으로 수행되어야 한다.
    = 한 트랜잭션의 중간 결과는 다른 트랜잭션에게 숨겨져야 한다
    이러한 isolation 성질이 보장되지 않으면 트랜잭션이 원래 상태로 되돌아갈 수 없게 된다.
    이 성질을 보장할 수 있는 가장 쉬운 방법은 모든 트랜잭션을 순차적으로 수행하는 것 이다. 하지만 병렬적 수행의 장점을 얻기 위해 DBMS는 병렬적으로 수행하면서도 일렬(serial) 수행과 같은 결과를 보장할 수 있는 방법을 제공한다.

    4. Durability (지속성)

    트랜잭션이 성공적으로 완료되어 커밋되고 나면, 해당 트랜잭션에 의한 모든 변경은 향후에 어떤 소프트웨어나 하드웨어 장애가 발생되더라도 보존되어야 한다.

    트랜잭션의 세 가지 가능한 결과 형태(Gray 외, 1981)

    Transaction Isolation Level

    : 트랜잭션에서 일관성 없는 데이터를 허용하도록 하는 수준

    • 데이터베이스는 위에서 언급한 ACID 특성와 같이 트랜잭션이 독립적인 수행을 하도록 한다.
    • 한 트랜잭션(커넥션)이 DB 상태를 점유하는 동안 다른 트랜잭션(커넥션)이 접근하지 못하도록 막는 것을 Locking이라 한다 ❗❗

    하지만 Locking을 통해 무조건적으로 다른 커넥션을 막는다면, 트랜잭션의 수행이 serialize되고 데이터베이스의 성능이 저하될 수 있다.
    반대로, 성능을 높이기 위해 Locking의 범위를 줄이면, isolation 특성이 보장받지 못해 잘못된 값을 처리하게 될 확률이 생긴다. 따라서 데이터베이스 특성에 적합한 효율적인 Locking 방법을 선택해야 한다.

    다음은 Transaction Isolation Level의 종류를 나타낸다.

    1. Read Uncommitted (Level 0)
      • SELECT 문장이 수행되는 동안 해당 Shared Lock이 걸리지 않는다
      • 트랜잭션이 현재 처리중이거나, 아직 Commit되지 않은 데이터를 다른 트랜잭션이 읽는 것을 허용한다
      • ex) User1이 Data A를 B로 변경하는 동안 User2는 아직 완료되지 않은(Uncommitted) 트랜잭션이지만 B를 읽을 수 있다
      • 데이터베이스의 일관성을 유지하는 것이 불가능하다
    2. Read Committed (Level 1)
      • SELECT 문장이 수행되는 동안 해당 데이터에 Shared Lock이 걸린다
      • 트랜잭션이 수행되는 동안 다른 트랜잭션이 접근할 수 없어 대기하게 된다(Commit이 이루어진 트랜잭션만 조회 가능하다)
      • SQL Server가 Default로 사용하는 Isolation Level
      • ex) User1이 Data A를 B로 변경하는 동안 User2는 해당 데이터에 접근할 수 없다
    3. Repeatable Read (Level 2)
      • 트랜잭션이 완료될 때 까지 SELECT 문장이 사용하는 모든 데이터에 Shared Lock이 걸린다
      • 트랜잭션이 범위 내에서 조회한 데이터 내용이 항상 동일함을 보장한다
      • 다른 사용자는 트랜잭션 영역에 해당되는 데이터를 수정할 수 없다
    4. Serializable (Level 3)
      • 트랜잭션이 완료될 때 까지 SELECT 문장이 사용하는 모든 데이터에 Shared Lock이 걸린다
      • 완벽한 Read 일관성 모드를 제공한다
      • 데이터의 일관성 및 동시성을 위해 MVCC(Multi Version Concurrency Control - 데이터 조회 시 Lock을 사용하지 않고 데이터의 버전을 관리해 데이터의 일관성 및 동시성을 높이는 기술)을 사용하지 않는다
      • 다른 사용자는 트랜잭션 영역에 해당되는 데이터를 수정/입력할 수 없다


    낮은 단계의 Isolation Level을 채택할 경우에는 다음과 같은 문제점들이 발생할 수 있다.

    • Dirty Read
      • (커밋되지 않은) 수정중인 데이터를 다른 트랜잭션에서 읽을 수 있도록 허용할 때 발생
      • 특정 트랜잭션에서 아직 실행이 끝나지 않은 다른 트랜잭션에 의한 변경사항을 보게 되는 경우
    • Non-Repeatable Read
      • 한 트랜잭션에서 같은 쿼리를 두 번 실행할 때, 그 사이 다른 트랜잭션 값을 수정 또는 삭제하면서 두 쿼리의 결과가 상이하게 나타나는 현상(일관성 깨짐)
    • Phantom Read
      • 한 트랜잭션 안에서 일정 범위의 레코드를 두 번 이상 읽었을 때, 첫 번째 쿼리에서 없던 레코드가 두 번째 쿼리에서 나타나는 현상
      • 트랜잭션 도중 새로운 레코드 삽입을 허용하기 때문에 나타나는 현상
    https://i.stack.imgur.com/U9oBZ.png


    DeadLock

    : 두 개 이상의 트랜잭션이 특정 자원(테이블 또는 레코드)의 잠금(Lock)을 획득한 채, 다른 트랜잭션이 소유하고 있는 잠금을 요구하는 상태. 아무리 기다려도 소유권을 받을 수 없으며 복수의 트랜잭션을 사용하다 보면 데드락이 발생할 수 있다.

    https://github.com/JaeYeopHan/Interview_Question_for_Beginner/raw/master/Database/images/deadlock.png

    MySQL MVCC에 따른 특성에 의해 트랜잭션에 갱신 연산(Insert, Update, Delete)를 실행하면 Lock을 얻는다
    Transaction1이 Table B의 첫 번째 레코드의 lock을 얻고, Transaction2도 Table A의 첫 번째 레코드의 lock을 얻었다고 하자

    Transaction 1> create table B (i1 int not null primary key) engine = innodb; Transaction 2> create table A (i1 int not null primary key) engine = innodb; Transaction 1> start transaction; insert into B values(1); Transaction 2> start transaction; insert into A values(1);

    이 때, 트랜잭션을 commit 하지 않은 채 서로의 첫 번째 레코드에 대한 lock을 요청하면

    Transaction 1> insert into A values(1); Transaction 2> insert into B values(1); ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction

    데드락이 발생한다. 일반적인 DBMS는 데드락을 독자적으로 검출하여 보고한다.

    데드락을 막기 위해서는

    1. 트랜잭션을 자주 커밋한다
    2. 정해진 순서로 테이블에 접근한다
      • (위의 예시에서는)Transaction1이 테이블 B ➡ A의 순으로 접근하고, Transaction2는 테이블 A ➡ B의 순으로 접근했기 때문에 데드락이 발생했다. 트랜잭션들이 동일한 테이블 순서에 의해 접근하도록 한다
    3. 읽기 Lock 획득(SELECT ~ FOR UPDATE)의 사용을 피한다
    4. 한 테이블의 복수 레코드를 복수 커넥션에서 순서 없이 갱신하면 교착상태가 발생하기 쉽다
      • 테이블 단위의 Lock을 획득해 갱신을 직렬화하면 동시성은 떨어지지만 데드락을 회피할 수 있다

    위와 같은 방법들이 사용된다.

    참고자료:

Designed by Tistory.