DB Transaction

2020. 12. 5. 23:55데이터베이스/이론

DB Transaction

Transaction이란 dbms의 동시접근과 시스템 장애시 일관성을 유지하기 위해 상태를 변환시키는 일련의  연산 및 작업을 뜻한다. 한 트랜잭션 단위의 명령어의 함께 성공 및 집합 만이 존재한다. 만약 하나의 트랜잭션 집단 모음에서 명령어가 실행되거나 실패되는 것을 의미한다. 

 

일반적으로 Transaction의 경우 ACID라는 규약을 따르는데 이것에 대해 알아보자

 

ACID

Atomicity

트랜잭션의 All or Nothing 정책, 하나의 명령어라도 실패하면 모두 롤백 시킨다.

 

Consistency

단독 실행 시 성공하면 데이터베이스의 일관성을 보장.

 

Isolation

다른 트랜잭션의 영향을 고려하지 않고 , 트랜잭션 수행결과를 이해할 수 있어야함. 여러 트랜잭션들의 동시 수행이 어떤 직렬가능성과 동일함을 보장.

 

Durabiltiy 

트랜잭션이 커밋되면 어떤 경우라도 지속성 보장한다. 즉 결과가 영구적으로 유지되는 것이다. 

 

 

Transaction과 Schedules

Transaction의 연산

RTx(O): 객체 O에 대한 읽기

WTx(O): 객체 O에 대한 쓰기

CommitTx: Tx의 완료

AbortTx: Tx의 철회

 

- Tx는 DB의 읽기와 쓰기만으로만 상호작용할 수 있다. 

- DB는 한정된 객체들의 한정된 모임임. 객체의 삽입/삭제나 객체들 사이의 관련성은 몇 가지 추가적인 이슈 발생시킴

 

 

Schedules

어떤 Tx내에서 두 연산의 순서는 Schedule에서도 동일 순서임

Complete Schedule: Commit이나 Abort가 발생하는 Schedule

Serial Schedule: Tx들을 하나씩 순차적인 실행하는 Schedule

 

동시 실행

동시 실행의 목적: Tx는 동시 수행은 Isolation을 유지를 어렵게 하나 다음의 장점을 요함 

 

- 시스템의 시간당 처리량 증가: 한 Tx를 위해 cpu가 기다릴 때 다른 Tx를 실행

- 평균 응답 시간을 줄임: 짧은 Tx가 긴 Tx뒤에 실행 됨으로써 평균 응답시간 짧아짐.

 

Serializable Schedule

하나의 Schedule의 결과가 하나의 Serial Schedule의 결과와 동일한것.

 

Serializable Schedule의 예시

Interleaved Execution(상호 배치 실행)

Reading Uncommitted Data(미완료 데이터 읽기, Dirty Read)

 

 

예시) T1은 A에서 B로 돈을 100원 보냄

         T2는 A와 B를 각각 6% 증가

 

Schedule

 

1) T1이 A에서 100원을 감함

2) T2가 A와 B를 읽고 6% 증가

3) T1이 B에 100원을 더함

 

Error: T1연산이 모두 실행된 후 6%가 증가되어야 하는데 6%를 증가시킨 후 100원을 더해버리면 A의 일관성이 일치하지 않는다

 

Unrepeatable Reads(비반복 읽기, RW conflict)

T1이 읽은 값을 T2가 수정할 수 있음. T1이 A를 다시 읽으면 처음 읽었을 때와 다르게 값이 다르다.

 

예시) 어느 서점의 복사본 수를 A라고 하자

 

1) Tx를 통해 A를 읽고 0보다 큰지를 검사하고 고객의 주문량 만큼 A를 감소한다. 

2) T1과 T2 가 직렬 수행시 아무 문제도 발생하지 않지만 동시에 실행할 시에 문제가 발생한다. 

 

 

Overwriting Uncommitted Data(미완료 데이 터 겹쳐 쓰기, WW Conflict)

수행 중인 T1이 이미 수정한 A의 값을 T2가 겹쳐 쓰기를 할 수 있음. 즉 T1이 수정을 했는데 수정한 A의 값을 T2가 겹쳐서 쓸 때 다른 값이 될 수 있다.

 

T2는 Harry의 급여를 $1000으로 결정

T1는 Larry의 급여를 $2000으로 결정

T2는 Larry의 급여를 $1000으로 결정

T1는 Harry의 급여를 $2000으로 결정

 

 

Abort Transcation을 포함하는 스케줄

Abort가 발생했으면 이미 실행한 연산들을 완전히 undo 해야함.

 

예)

 

1) 계좌이체 T1이 A에서 100원을 감함

2) 이자 입금 T2이 A와 B를 읽고 6% 추가하고 commit함.

3) T1이 abort함.

 

T1이 기록한 데이터를 abort, T2가 기록한 데이터를 abort한다. 하지만 T2는 이미 commit을 진행했기 때문에 T1은 abort 됨.

 

-> 즉 여기서 Schedule은 Unrecoverable Schedule임.

 

Recoverable Schedule

트랜잭션이 기록한 데이터만 읽을 수 있고 실행한 데이터에 접근할 수 없다. 즉 실행 중인 데이터를 트랜잭션이 읽을 수 없게 해야한다. 

 

1) T1이 A = 1을 2로 수정

2) T2가 A를 수정

3) T2 commit

4) T1이 abort(A를 1로 복귀)

 

-> T2의 연산은 모두 상실되게 된다. 

 

 

동시성 해결법

Locking protocol을 통해 해결한다. Shared, exclusive Locking

 

Strict 2PL(Two-Phase Locking Protocol)

규칙1: 트랜잭션 Tx가 객체를 읽기 원할때 전용 Lock을 요구하게 된다. 

규칙2: Tx가 소유한 모든 lock은 Tx가 완료될 때 해제됨.

 

 

Lock 요구 및 획득 규칙

1. 어떤 Tx에 의해 공용 lock이 걸린 객체에 다른 Tx가 공용 lock을 요구 하면 획득되나 전용 lock을 요구하면 기다려야한다. 

2. 이미 전용 lock을 획득한 객체는 바로 읽을 수 있다. 

 

 

 

DeadLock

Schedule

1) T1이 A에 전용 Lock을 설정

2) T2가 B에 전용 Lock을 설정

3) T1이 B에 전용 Lock을 설정 - wait

4) T2가 A에 전용 Lock을 성정 - wait

 

위와 같이 스케줄이 작성되면 Lock이 해결될 때까지 3, 4의 경우 1, 2가 기다릴 때 까지 3, 4의 실행은 완전히 멈춰버린다. 즉 이런 상황을 Dead Lock이라고한다.

 

복구 방법

Time out: Tx의 대기시간이 일정시간을 초과하면 이 Tx를 abort함.

대기 그래프: 사이클 발생 검사, 사이클에 포함된 희생 Tx 선택하여 abort함 

 

DeadLock 회피방법

 

Lock Downgrade 기법(대부분 상용기법)

 

테이블 갱신 SQL 문장을 처리하려면 갱신하려는 테이블의 전체 행에 대하여 전용 lock을 획득한 다음에 이 갱신문장의 조건절에 부합하지 않는 행들의 lock을 공용 lock으로 강등시킨다. 

 

즉 테이블의 전체행에 전용 lock을 획득한 다음 갱신 문장의 조건절에 부합하지 않은 행들의 lock을 공용 lock으로 강등시킨다. 

 

 

성능 변화

- 처음에는 활성화된 Tx들의 수에 비례해서 처리율이 증가됨.

- 점점 Tx가 많아지면서 대기 지연이 커지고 처리율의 증가가 둔화된다. 

 

처리율 증가 방법

- Lock의 대상의 크기를 줄임

- Lock의 소유시간을 줄임

- Hot spots(집중적 발생) 객체를 줄임

 

 

 

Lock 오버헤드를 제어하기 위한 Tx의 특성을 명시할 수 있음

- 접근 모드: READ ONLY 모드, READ WRITE 모드

- 집단 크기: 기록되는 에러 조건 수

- 고립 수준: 어떤 Tx가 다른 Tx의 연산에 노출되는 수준

 

고립 수준

 

 

 

위의 설정을 통해 아래와 같은 문제가 발생하거나 발생안할 수 있다. 

 

여기서 phantom Read란 

 

한 트랜잭션 내에서 같은 쿼리를 두번 수행했는데, 첫번째 쿼리에 없던 유령 레코드가 두번째 쿼리에서 나타나는 현상을 의미한다.