13회차 데이터베이스 | DB 트랜잭션, 트랜잭션 격리수준 관련 내용 정리

728x90
DB 트랙잭션과 트랙잭션 특성 4가지,
DB 트랜잭션 격리수준

DB 트랜잭션 | Transaction

1) 트랜잭션 개념

(1) 트랜잭션

  • DBMS에서 데이터 다루는 논리적 작업 단위
  • 여러 쿼리를 논리적으로 하나의 작업으로 묶어주는 것
  • DB에서 데이터 다루다가 장애 일어난 경우 → 데이터 복구 작업의 단위
  • DB에서 여러 트랜잭션이 동시에 같은 데이터 다룰 경우 → 동시 접근 작업들 분리하는 단위

(2) 트랜잭션 제어어 | TCL (Transaction Control Language)

  • start transation : 트랜잭션 시작
SET TRANSACTION NAME <이름> 
  • commit : 트랜잭션 종료
COMMIT 
  • rollback : 트랜잭션 무효화
ROLLBACK {TO <savepoint>} //트랜잭션 전체 or <savepoint> 까지 무효화 복귀시킴
  • savepoint : savepoint 생성
SAVEPOINT <savepoint> 

→ 트랜잭션 너무 길면 트랜잭션 중간 지점에 수정 내용을 반영하는 포인트 <저장점>

→ 중간 오류로 rollback 해야 할 때, 트랜잭션 전체 rollback 대신에 savepoint까지만 롤백할 수 있다.

→ 트랜잭션 안에 여러 개 만들 수 있다

 

(3) 트랜잭션 상태

트랜잭션 상태도

활동 (Active) : 트랜잭션이 실행 중에 있는 상태, 연산들이 정상적으로 실행 중인 상태

장애 (Failed) : 트랜잭션이 실행에 오류가 발생하여 중단된 상태

철회 (Aborted) : 트랜잭션이 비정상적으로 종료되어 Rollback 연산을 수행한 상태

부분 완료 (Partially Committed) : 트랜잭션이 마지막 연산까지 실행했지만, Commit 연산이 실행되기 직전의 상태

완료 (Committed) : 트랜잭션이 성공적으로 종료되어 Commit 연산응 실행한 후의 상태

 

(4) 트랜잭션 수행 과정

→ 다음의 단위를 [하나의 트랜잭션 작업 단위]라고 봤을 때, 트랜잭션의 수행 과정을 보자.

//트랜잭션의 시작과 끝을 표시하는 SQL 문법
START TRANSACTION
	(1) 박지성 계좌에서 10,000원 인출 UPDATE문
	(2) 김연아 계좌에서 10,000원 입급 UPDATE문
COMMIT

트랜잭션 수행 과정

  1. 트랜잭션은 DB에 저장된 테이블을 읽어와서 주기억장치 버퍼에 저장해두고,
  2. 버퍼에 저장된 데이터로 (작업 단위)를 모두 처리 한 뒤,트랜잭션이 임시 종료 선언한다.
  3. DBMS가 일괄적으로 하드디스크에 접근하여 수정된 데이터들을 DB에 기록한다.

2) 트랜잭션 특징 | ACID 성질 (4)

   (1) Anomicity (원자성)

: 트랜잭션 작업은 (전부 수행 O) or (전부 수행X) 되어야 한다. all or nothing

   (2) Consistency (일관성)

 : 트랜잭션 수행 전과 후 데이터베이스는 항상 일관된 상태 유지해야 한다.

ex. 테이블 기본키 속성 유지되어야 한다는 것

ex. 계좌 A→B 이체 시 (A+B) 돈의 총합은 처리 전/후에도 같아야 한다는 것

   (3) Isolation (고립성)

: 동시 수행되는 트랜잭션들은 서로 방해받지 않고 독립적 수행되어야 한다.

→ 데이터베이스는 클라이언트들이 같은 데이터 공유하는 목적이므로 여러 트랜잭션이 동시에 수행될 수밖에 없다.

→ 이때 한 트랜잭션 수행 중에 다른 트랜잭션의 끼어들거나, 상호 간섭, 충돌 일어나지 않는 것이 ‘고립성’ 이다.

    (4) Durability (지속성)

: 수행 성공적으로 완료된 트랜잭션은 변경된 데이터 영구 저장해야 한다.

→ 정상 완료(commit) 혹은 부분 완료(partial comit)된 데이터는 DBMS가 책입지고 데이터베이스에 기록하는 성질


3) 트랜잭션과 DBMS

→ DBMS는 트랜잭션이 (원자성, 일관성, 고립성, 지속성) 유지할 수 있도록 지원한다.

(1) 원자성 유지 | DBMS 회복 프로그램 활용

  • DBMS는 회복(복구) 프로그램 작동시켜 DB 변경점을 수시로 로그에 기록하고 있다가 트랜잭션 상에 문제 발생할 경우 원래 상태로 복귀시킨다.

(2) 일관성 유지 | DBMS 무결성 제약조건 & 동시성 제어 활용

     a) 데이터 일관성 유지

     → DBMS는 변경된 데이터를 미리 정의한 무결성 제약조건으로 검사하며 데이터 일관성 지켜준다.

     b) 트랜잭션 동시 수행 중에도 데이터 일관성 유지

     → DBMS는 동시성 제어 알고리즘을 작동시켜 트랜잭션들이 질서있게 접근하도록 하는 방식으로 데이터 일관성 지켜준다.

(3) 고립성 유지 | DBMS 동시성 제어 활용

→ DBMS 는 동시성 제어 알고리즘을 가동시켜 여러 트랜잭션이 동시에 같은 데이터 접근 시 트랜잭션 별로 순서대로 접근하는 것처럼 제어한다.

(4) 지속성 유지 | DBMS 회복 & 책임지고 저장시킴

→ DBMS는 회복(복구) 프로그램 작동시켜, 문제가 있을 때는 되돌리고, 문제 없으면 책임지고 일괄적으로 DB에 기록한다.


 트랜잭션 동시에 [읽기/쓰기] 시나리오

트랜잭션 [읽기/쓰기] 시나리오

[상황1] : 동시에 읽기만 하는 건 문제가 없다.

[상황2] : T1이 읽기, T2가 쓰기 작업 → ‘트랜잭션 고립 수준’ 명령어로 해결

    → 상황 3처럼 동시성을 락을 걸면 너무 과도하게 동시 진행 정도를 막는다.

    → 따라서, 트랜잭션 동시성을 높이고자, 트랜잭션 고립 수준을 활용한다.

[상황3] : T2, T2 모두 쓰기 작업 : [갱신손실 문제] → 동시성 제어(Lock) 로 해결


동시성 제어 | Currency Control

→ 앞서 보았듯이, DBMS가 지원하는 기능 중 [동시성 제어]는 트랜잭션의 일관성과 고립성을 지원하고 있다.

→ 데이터베이스는 ‘공유’가 목적이므로, 트랜잭션 동시 수행은 불가피하다.

→ 다만, 동시에 수행되는 트랜잭션이 같은 데이터에 접근할 때 ‘동시성 제어’를 통해 데이터 일관성을 지켜줄 필요가 있다.

→ 그리고 이는 DBMS가 지원하는 기능 중 하나이다.

1) 동시성 제어 개념

동시성 제어 : 트랜잭션들이 동시에 같은 데이터에 접근할 경우, 데이터 일관성을 해치지 않도록 제어하는 기능

2) 갱신손실 문제 | Lost Update

- 두 개의 트랜잭션이 한 개의 데이터 동시에 갱신할 때 발생하는 문제

- 하나의 트랜잭션 갱신 내용을 다른 트랜잭션이 덮어씀으로써 갱신 무효화 발생

- 데이터베이스에 절대 발생하면 안 되는 현상

💡 [설명] X = 1000 인 상태이다.
   T1은 X-100
   T2는 X+100

 의도는 T1이 만든 900을 → T2가 1000으로 만드는 것이다.

 그런데, 동시성 제어가 없으면 T1도, T2도 HDD에서 주기억장치 버퍼에 각자 처리할 데이터인 (X= 1000 데이터)를 각각 들고가서 각자 작업을 동시 수행 해버리고 만다.

즉, [동시성 제어] 없으면 T2는 애초에 잘못된 (T1 갱신 전의) 데이터를 들고 작업을 처리하게 되고 그러면서 T1의 갱신 작업이 손실된 채로, T2의 작업이 진행한다.

⇒ 두 개의 트랜잭션이 ‘한 개의 데이터’를 동시에 갱신할 때 동시성 제어가 되지 않은 상황에서는 T1의 갱신 작업이 손실되어 버리는 [갱신손실] 문제가 발생한다.

[ 트랜잭션이 동시에 하나의 데이터 접근 시 발생하는 문제]

모순성(Inconsistency)
- 다른 트랜잭션들이 해당 항목 값을 갱신하는 동안
 한 트랜잭션이 두 개의 항목 값 중 어떤 것은 갱신되기 전의 값을 읽고 다른 것은 갱신된 후의 값을 읽게 되어 데이터의 불일치가 발생하는 상황

연쇄 복귀(Cascading Rollback) 
- 두 트랜잭션이 동일한 데이터 내용을 접근할 때 발생
- 한 트랜잭션이 데이터를 갱신한 다음 실패하여 Rollback 연산을 수행하는 과정에서 갱신과 Rollback 연산을 실행하고 있는 사이에 해당 데이터를 읽어서 사용할 때 발생할 수 있는 문제

 

3) 락 | Lock

→ 두 트랜잭션이 (쓰기, 쓰기) 상황에 대한 해결을 논한다.

⬛ 락의 개념

- 한 트랜잭션이 데이터 읽거나 수정할 때, 데이터 접근 잠금 장치

- 한 트랜잭션이 자신이 사용할 데이터에 락을 걸면, 다른 트랜잭션은 락 해제될 때까지 대기해야 한다.

- 락을 걸면 동시 수행되는 트랜잭션이 동일한 데이터 접근 시, 데이터 X에 대한 갱신을 순차적으로 진행할 수 있으므로 [갱신손실] 문제를 해결할 수 있다.

💡 [설명] 동시성 제어로 ‘락’을 활용하고
         똑같이 X=1000인 데이터에 T1, T2가 동시에 접근했다고 치자.

X = 1000 
T1 : x-100
T2 : x+100


T1은 자신이 작업할 X에 lock(X) 걸고, 트랜잭션 작업을 수행한다. x-100
     작업 마치고 x=900 된 채로, unlock(X) 걸어준다.


T2는 X에 접근하려고 할 때, 이미 lock이 걸려있어서 대기하다가,
     T1이 unlock 해준 시점에 x=900을 들고 가서 lock 걸고 트랜잭션 작업을 수행한다. x+100
    작업 마치고 x=1000 된 채로, unlock(X) 걸어준다.

이렇게 되면 두 개의 트랜잭션이 동시에 한 개의 데이터를 갱신하려고 할 때 나타났던 갱신손실 문제를 '동시성 제어' 락 Lock 활용하여 해결하게 된다.

[ 락의 유형 (2) ] 

(1) 공유락 | shared lock (LS) : 데이터 읽기 표시하는 락

(2) 배타락 | exclusive lock (LX) : 데이터 쓰기 표시하는 락


[공유 락과 배타 락 사용 규칙] 


(1) 데이터에 락이 걸려있지 않다면 트랜잭션이 데이터에 락을 걸 수 있다.
(2) 락의 요청
     트랜잭션이 데이터 X를 읽기만 하면 LS(X) 요청
      트랜잭션이 데이터 X를 쓰기도 하면 LX(X) 요청
(3) 락의 허용
      다른 트랜잭션이 데이터에 LS(X) 걸어두면, LS(X) 요청은 허용 (읽기), LX(X) 요청은 불허용(쓰기)
      다른 트랜잭션이 데이터에 LX(X) 걸어두면, 모든 요청 불허용
(4) 트랜잭션은 락 허용받지 않은 상태에서는 대기 상태가 된다.

2단계 락킹 기법 | 2 phase locking (=2PL)

(1) 2PL 개념

  • 트랜잭션이 락을 걸고 해제하는 [시점]을 2단계로 분리시킨 기법

1) 확장 단계 : 락 걸기만 한다.

2) 수축 단계 : 락 해제만 한다.

(2) 사례 

두 개의 데이터에 두 개의 트랜잭션이 접근하여 갱신하는 작업을 한다고 치자.

A. [2단계 락킹 사용 안한 경우]

→ 문제 원인 :T1이 A에 락을 걸고 작업하다가 (중간에 락을 해제시켜서) T2가 A에 접근 가능했기 때문이다.

2PL 사용 안한 경우 문제

B. [2단계 락킹 사용한 경우]

→ 2단계 락킹으로 (lock, unlock) 시점 분리하자, 한 트랜잭션 작업 완료하기 전에는 락을 해제하지 않게 되어 데이터 일관성 제약 지켜짐

2PL 적용

4)  데드락 | DeadLock (= 교착상태)

→ 2단계 락킹 기법 사용하면 락 시점을 분리시켜서 데이터 일관성을 유지할 수 있었다.

→ 그렇지만, 두 개 이상의 트랜잭션이 각각 자신의 데이터에 대하여 락 획득한 상태로 상대방의 락을 요청하면 무한 대기 상태에 빠진다. 이를 ‘데드락’ 이라고 한다.

(1) 데드락 

두 개 이상의 트랜잭션이 각각 자신의 데이터에 대해 락을 획득하고 상대 데이터에 대하여 락을 요청하면서 무한 대기 상태에 빠지는 현상

(2) 예시 설명

도서번호1인 책 가격, 도서번호2인 책 가격 두 개의 데이터에 동시 접근하는 트랜잭션이 있다.

T1 작업 : 도서번호 1인 도서 100원 올리고, 도서번호 2인 도서 100원을 올린다.

T2 작업 : 도서번호 2인 도서 10% 인상하고, 도서번호 1인 도서 10% 인상한다.

데드락 상황

→ 즉, T1, T2 모두 서로가 획득한 락을 쥔 상태로, 상대의 락을 요청하며 ‘무한 대기 상태’에 빠지게 된다.

→ 일반적으로 데드락 발생하면 DBMS가 T1, T2 중에서 하나를 강제로 중지시켜 한 트랜잭션은 정상 실행되고, 중지시킨 트랜잭션은 원래 상태로 되돌려놓는다.

:[데드락 예방 기법]
→ 각 트랜잭션이 실행되기 전 필요한 데이터를 모두 Lock(락킹) 해주는 방식
단, 예방 기법은 데이터가 많이 필요할 경우 사실상 모든 데이터를 Lock 걸어줘야 해서 트랜잭션 병행성 보장 못한다. 또한 몇몇 트랜잭션은 계속 처리를 못하게 되어 ‘기아 상태’ 발생할 수 있다.


[데드락 회피 기법]
→ 자원 할당할 때 시간 스탬프 (Time Stamp) 사용하여 교착상태 일어나지 않도록 회피하는 방법

1) Wait-Die 방식
다른 트랜잭션이 이미 점유하고 있는 데이터를 TimeStamp 시간에 따라 대기하거나 포기하는 방식

2) Wound-Wait 방식
다른 트랜잭션이 이미 점유하고 있는 데이터를 TimeStamp 시간에 따라 빼앗거나 대기하는 방식

트랜잭션 고립 수준

→ 두 트랜잭션이 (읽기, 쓰기) 상황에 대한 해결을 논한다.

1)  트랜잭션 동시 실행 문제 (3)

편의 상 T1 (읽기), T2 (쓰기) 하는 트랜잭션이라 가정한다.

   1) 오손 읽기 | Dirty Read T

T2가 쓴 작업이 Rollback되어 T1이 읽은 데이터가 무효화 된 문제
  • 읽기 작업을 하는 T1이 쓰기 작업을 하는 T2가 작업한 중간 데이터를 읽기 때문에 발생하는 문제
  • 작업 중인 T2가 작업 커밋 전 Rollback(롤백) 할 경우, T1은 무효화된 데이터를 읽은 것이고 잘못된 결과를 도출하게 된다.
  • 즉, T1이 T2가 Rollback 되기 전 T2가 쓰기한 데이터를 읽었는데, T2가 Rollback이 되면서 T1이 읽은 값이 의미가 없는 값이 되어버리며 문제가 발생

   2) 반복 불가능 읽기 | Non-Repeatable Read

T1이 읽기 작업을 다시 반복했을 때, 이전 결과가 반복되지 않는 현상
트랜잭션 중간에 다른 트랜잭션이 갱신한 데이터를 읽으면서 (결과값이 반복되지 않는) 현상
  • T1이 읽고/ T2가 (Update) 갱신 작업을 한 상태에서/ 다시 T1이 변경된 데이터를 읽었을 때 다른 결과 발생하는 문제
  • 즉, T2가 정상 종료해서 무효화된 데이터를 읽은 건 아니지만, T1 입장에선 같은 SQL문이 다른 결과를 도출하며 발생한 문제이다.

   3) 유령 데이터 읽기 | Phantom Read

T1이 읽기 작업 다시 반복했을 때, 이전에 없던 유령 데이터 나타난 현상
트랜잭션 중간에 다른 트랜잭션이 삽입한 데이터를 읽으면서 (결과값에 유령데이터 나타난) 현상
  • T1이 읽고 / T2가 (INSERT) 삽입 작업을 한 상태에서 / 다시 T1이 변경된 데이터를 읽었을 때 이전에 없던 데이터 (유령 데이터)가 나타나는 현상

2) Transaction 격리 수준 명령어 | Transaction Isolation Level Instruction

⇒ 동시에 수행되는 트랜잭션끼리 어느 정도의 영향을 끼칠 수 있는지 정하는 것

DBMS는 트랜잭션 동시에 실행시키면서 락보다 완화된 방식으로 문제를 해결하고자 명령어를 제공한다.

→ 다음의 표는 고립 수준에 따른 [트랜잭션 동시 실행 문제] 발생 여부를 표현한 표이다.

고립 수준에 따른 문제 발생 여부 표

고립성이 높을수록 동시성은 낮아지고, 고립성이 낮을수록 동시성은 높아진다.

고립성이 너무 높으면 트랜잭션들이 과도하게 고립되어 동시성 해치고,
고립성이 너무 낮으면 트랜잭션들이 동시에 꼬이면서 발생하는 문제가 많이 생긴다.

 

1) READ UNCOMMITED | 고립 lv.0 (동시성 높음)

 커밋 X 데이터에도 접근 가능

(1) 아무런 공유락을 걸지 않는다. (단, 갱신손실 문제 때메 배타락은 건다)


(2) 다른 트랜잭션에 공유락과 배타릭 걸린 데이터도 대기 안하고 읽는다.


READ UNCOMMITED

2) READ COMMITED | 고립 lv.1

커밋된 데이터만 접근 가능

(1) 오손 페이지 참조 피하고자, 자신이 데이터 읽는 동안에는 공유락을 걸되, 트랜잭션 끝나기 전에도 해지 가능하다.

(2) 다른 트랜잭션이 설정한 공유락은 읽지만, 베타락을 읽지 못한다.

READ COMMITED

3) REPEATABLE READ | 고립 lv2

 한 트랜잭션 내부에서 반복 조회한 데이터는 계속 같은 값으로 조회됨 (non-repeatable Read 문제 해결)

(1) (공유락, 배타락)을 트랜잭션 종료될 때까지 유지

(2) 다른 트랜잭션이 설정한 고유락은 읽지만, 배타락은 읽지 못한다.

(3) 다른 트랜잭션이 공유락 걸린 데이터 UPDATE는 못하지만, 나머지 범위에 INSERT는 가능하다.

        → 그래서 여전히 유령 데이터 읽는 문제는 발생함

예를 들어, SELECT number FROM A WHERE number BETWEEN 1 and 10을 수행하였고, 이 범위에 해당하는 number가 2 or 3이 있는 경우 다른 사용자가 number가 2 or 3인 행에 대한 UPDATE가 불가능하지만 나머지 범위에 대해서 행을 INSERT하는 것이 가능하다.

REPEATABLE READ

4) SERIALIZABLE | 고립 lv.3 (동시성 낮음) 순차적 진행

→ 트랜잭션이 데이터 읽으면, 다른 트랜잭션은 조회만 가능한 수준
→ 실행 중인 트랜잭션이 다른 트랜잭션으로부터 완벽하게 분리된다.

(1) (공유락, 배타락) 트랜잭션 끝날 때까지 유지

(2) 데이터 집합에 범위를 지어 잠금 설정 가능해서, 다른 사용자가 데이터 UPDATE/INSERT 하고자 할 때 완벽하게 분리 가능하다.

예를 들어, SELECT 문이 사용하는 모든 데이터에 공유락이 걸리므로 다른 사용자는 그 영역에 해당되는 데이터에 대한 수정(UPDATE) 및 입력(INSERT)가 불가능하다.

앞의 Repeatable Read의 경우에는 1에서 10사이의 number에 대한 삽입이 가능하였지만
SERIALIZABLE은 SELECT의 대상이 되는 모든 테이블에 공유락을 설정하는 것과 같아서 나머지 범위에 대한 INSERT가 불가능하다.

SERIALIZABLE

728x90