트랜잭션과 교착상태

gojung·2021년 11월 8일
0

CS

목록 보기
1/4

트랜잭션

데이터베이스의 상태를 변환시키는 하나의 논리적 기능을 수행하기 위한 작업의 단위

👉무조건 한꺼번에 수행되어야 하는 연산

트랜잭션의 특징


1. 원자성 Atomicity
트랜잭션이 데이터베이스에 전부 반영되거나, 전혀 반영되지 않아야 한다.

2. 일관성 Consistency
트랜잭션의 결과는 항상 일관성이 있어야 한다. 트랜잭션이 진행되는 동안 DB가 변경되더라도 트랜잭션 시작 시점에 참조한 DB로 작업을 수행한다.
-> 사용자가 일관성 있는 데이터를 볼 수 있다.
3. 독립성 Isolation
둘 이상의 트랜잭션이 동시에 실행되고 있을 경우, 하나의 트랜잭션은 다른 트랜잭션에 관여할 수 없다.

4.지속성 Durability
트랜잭션이 성공적으로 완료되었을 경우, 결과는 DB에 영구적으로 반영되어야만 한다.

Commit / Rollback

Commit

트랜잭션이 성공적으로 끝났고 DB가 일관성 있는 상태에 있을 때, 트랜잭션의 결과를 DB에 반영하기 위한 연산

mysql에서는 수행했던 트랜잭션이 로그에 저장되며, 해당 로그를 대상으로 이후 Rollback 연산을 진행할 수 있다.

Rollback

트랜잭션이 비정상적으로 종료되어 트랜잭션의 원자성이 깨졌을 경우, 트랜잭션을 처음부터 다시 시작하거나 트랜잭션을 통으로 취소한다.

동시성 제어

다중 사용자 환경을 지원하는 DB시스템에서 여러 트랜잭션 간의 간섭으로 문제가 발생하지 않도록 트랜잭션의 실행 순서를 제어하는 기법

동시에 진행되는 트랜잭션들이 서로 간섭하면 벌어지는 문제

  • 갱신 분실(lost update) 트랜잭션들이 동일한 데이터를 동시에 갱신하는 경우에 발생. 또는 이전 트랜잭션이 데이터를 갱신한 후 트랜잭션이 종료하기 전에 나중 트랜잭션이 동일한 데이터를 갱신하여 갱신 값을 덮어쓰는 경우에 발생하는 문제
  • 연쇄 복귀(cascading rollback) or 회복 불가능(Unrecoverability) 여러 개의 트랜잭션이 데이터를 공유할 때, 특정 트랜잭션이 이전 상태로 복귀(rollback)할 경우 아무 문제 없는 다른 트랜잭션까지 연달아 복귀하게 되는 문제. 이때 한 트랜잭션이 이미 완료된 상태라면 트랜잭션의 지속성 조건에 따라 복귀 불가능
  • 불일치 분석(inconsistent analysis) 여러 개의 트랜잭션이 동시에 실행할 때 끼어들기로 인해 트랜잭션의 일관성이 유지되지 못하는 상황

    동시성 제어는 이러한 문제들을 방지하고 데이터의 무결성 및 일관성을 보장한다.

끼어들기를 허용하지 않고 순차적으로 실행하는 직렬 스케줄, 혹은 직렬 가능한 스케줄로 만들어야 한다.

다중사용자환경의 DBMS에서는 동시성(병행수행)을 최대한 보장하면서 직렬스케줄과 동일한 결과를 가지는 직렬 가능한 스케줄로 만드는 방법이 가장 좋다.

트랜잭션 스케줄

트랜잭션을 이루는 연산들의 실행 순서.

  1. 직렬 스케줄
  • 하나의 트랜잭션이 실행되면, 해당 트랜잭션이 완료되어야만 다른 트랜잭션이 실행될 수 있다.
  1. 비직렬 스케줄
  • 트랜잭션을 병행수행한다. 기존 트랜잭션이 진행 중이더라도 다른 트랜잭션이 실행될 수 있다.
  1. 직렬 가능 스케줄
  • 서로 영향을 주지 않는 직렬 스케줄을 비직렬적으로 수행

직렬 스케줄

  • 두 개의 트랜잭션이 Read 연산만을 수행할 것이라면, 상호 간섭이 발생되지 않으며 연산의 순서도 중요하지 않다.
  • 두 개의 트랜잭션이 같은 데이터 항목에 접근하지 않는다면 상호 간섭이 발생되지 않으며 연산의 순서도 중요하지 않다.
  • T1이 X에 Write연산을 하고 T2가 X에 Read 또는 Write 연산을 한다면 실행 순서는 중요하다.

Lock

동시성제어기법으로, 트랜잭션들이 동일한 데이터 항목에 대해 임의적인 병행 접근을 하지 못하도록 제어하는 것

  • 트랜잭션 T가 데이터 항목 X에 대해 Read(X) or Write(X)연산을 수행하려면 반드시 lock(X) 연산을 해주어야 함

  • 트랜잭션 T가 실행한 lock(X)에 대해서는 해당 트랜잭션이 종료되기 전에 반드시 unlock(x)연산을 해주어야 함

  • 트랜잭션 T는 다른 트랜잭션에 의해 이미 lock이 걸려 있는 X에 대해 다시 lock(X)를 수행시키지 못한다.

  • 트랜잭션 T가 X에 lock을 걸지 않았다면, unlock(X)를 수행시키지 못한다.

공유락 Shared Lock(S-lock)

•공유잠금을 설정한 트랜잭션은 데이터 항목에 대해 읽기 연산(read)만 가능하다.
ex) T1에서 x에 대해 S-lock을 설정했다면, T1은 read(x) 연산만 가능하다.
• 하나의 데이터 항목에 대해 여러 개의 공유잠금이(S-lock) 가능하다.
ex) T1에서 x에 대해 S-lock을 설정한 경우, 동시에 T2에서도 x에 대해 S-lock을 설정할 수 있다.
• 다른 트랜잭션도 읽기 연산(read) 만을 실행할 수 있다.
ex) T1에서 x에 대해 S-lock을 설정했다면, T2에서도 T1이 S-lock(x)을 실행하는 동안 read(x) 연산만 가능하다.

배타락 Exclusive Lock(X-lock)

• 배타잠금을 설정한 트랜잭션은 데이터 항목에 대해서 읽기 연산(read)과 쓰기 연산(write) 모두 가능하다.
ex) T1에서 x에 대해 S-lock을 설정했다면, T1은 read(x) 연산과 write(x) 연산 모두 가능하다.
• 하나의 데이터 항목에 대해서는 하나의 배타잠금(X-lock)만 가능하다.

  • 동시에 여러 개의 배타잠금은 불가능하다.
    ex) T1에서 x에 대해 X-lock을 설정했다면, T1에서 unlock(x)를 하기 전까지 T2에서 x에 대해 X-lock을 설정할 수 없다.
    • 다른 트랜잭션은 읽기 연산(read)와 쓰기 연산(write) 모두 불가능하다.
    ex) T1에서 x에 대해 X-lock을 설정했다면, T2에서는 T1에서 unlock(x)를 하기 전까지 read(x), write(x) 연산이 모두 불가능하다.


• S-lock만 동시 잠금이 가능하다.

  • 하나의 데이터 항목에 대해서 동시에 두 개 이상의 S-lock 설정이 가능하다는 의미.

잠금 규칙

  • 트랜잭션은 read(x) 연산을 실행할 때 S-lock(x)이나 X-lock(x) 중 하나를 실행해야만 한다.
  • write(x) 연산을 실행하기 위해서는 X-lock(x)을 실행해야 한다.
  • 연산 종료 후에는 unlock(x) 연산을 실행해야 한다.
  • S-lock(x)이나 X-lock(x) 연산 실행 후에만 unlock(x) 연산을 실행할 수 있다.

잠금 단위(Locking Granularity)

잠금의 대상이 되는 데이터 객체의 크기로 레코드의 필드 값, 레코드, 물리적 입출력 단위인 디스크부터 테이블이나 데이터베이스까지 하나의 잠금단위로 설정할 수 있다.

  • 잠금 단위가 클수록 동시성(병행성) 수준은 낮아지고, 동시성 제어 기법은 간단해진다.
  • 잠금 단위가 작을수록 동시성(병행성) 수준은 높아지고, 관리는 복잡해진다.

따라서 여러 개의 잠금단위를 설정해놓고 필요에 따라 혼용해야 한다.

교착상태 Deadlock

잠금은 대부분의 DBMS에서 사용되는 방식이지만 다음과 같은 한계가 존재한다.

  • 직렬 가능한 스케줄이 항상 보장되지 않는다 → 2단계 잠금 규약(2PL)으로 해결
  • 교착상태(deadlock)가 발생할 수 있다


Deadlock 발생

  • 상호 배제(mutual exclusion) 공유 자원을 함께 쓸 수 없어서 어느 한 프로세스가 독점적으로 사용해야만 한다.
  • 점유 대기(hold and wait) 프로세스들은 어느 자원을 점유한 상태에서 다른 자원을 요청한다.
  • 비선점(no preemption) 프로세스가 할당받은 자원을 강제로 빼앗을 수 없다.
  • 순환 대기(circular wait) 각 프로세스가 서로 순환적으로 다른 프로세스가 갖고 있는 자원을 요구한다
    네 가지를 모두 충족해야만 DeadLock이 발생한다.

Deadlock 탐지

  • 타임아웃 기반 탐지
  • 그래프 기반 탐지
  • 분산 데드락의 탐지
    타임아웃으로 주로 구현

Deadlock 방지

  • 트랜잭션을 자주 커밋한다.
  • 정해진 순서로 테이블에 접근한다. 위에서 트랜잭션 1 이 테이블 B -> A 의 순으로 접근했고, 트랜잭션 2 는 테이블 A -> B의 순으로 접근했다. 트랜잭션들이 동일한 테이블 순으로 접근하게 한다.
  • 읽기 잠금 획득 (SELECT ~ FOR UPDATE)의 사용을 피한다.
  • 한 테이블의 복수 행을 복수의 연결에서 순서 없이 갱신하면 교착상태가 발생하기 쉽다, 이 경우에는 테이블 단위의 잠금을 획득해 갱신을 직렬화 하면 동시성은 떨어지지만 교착상태를 회피할 수 있다.

트랜잭션의 격리 수준(isolation)

동시에 여러 트랜잭션이 처리될 때 특정 트랜잭션이 다른 트랜잭션에서 변경하거나 조회하는 데이터를 볼 수 있도록 허용할지 말지를 결정하는 것

  • READ UNCOMMITTED
  • READ COMMITTED
  • REPEATABLE READ
  • SERIALIZABLE

READ UNCOMMITTED

각 트랜잭션에서의 변경 내용이 COMMIT이나 ROLLBACK 여부에 상관 없이 다른 트랜잭션에서 값을 읽을 수 있다.
정합성에 문제가 많은 격리 수준이기 때문에 사용하지 않는 것을 권장한다. Commit이 되지 않는 상태지만 Update된 값을 다른 트랜잭션에서 읽을 수 있다.

문제

  • DIRTY READ현상 발생
    트랜잭션이 작업이 완료되지 않았는데도 다른 트랜잭션에서 볼 수 있게 되는 현상

READ COMMITTED

RDB에서 대부분 기본적으로 사용되고 있는 격리 수준이다.
Dirty Read와 같은 현상은 발생하지 않는다.
실제 테이블 값을 가져오는 것이 아니라 Undo 영역에 백업된 레코드에서 값을 가져온다.

문제

  • 트랜잭션-1이 Commit한 이후 아직 끝나지 않는 트랜잭션-2가 다시 테이블 값을 읽으면 값이 변경됨
  • 하나의 트랜잭션내에서 똑같은 SELECT 쿼리를 실행했을 때는 항상 같은 결과를 가져와야 하는 REPEATABLE READ의 정합성에 어긋난다.
  • 데이터의 정합성은 깨지고, 버그는 찾기 어려워진다.

REPEATABLE READ

MySQL에서는 트랜잭션마다 트랜잭션 ID를 부여하여 트랜잭션 ID보다 작은 트랜잭션 번호에서 변경한 것만 읽게 된다.
Undo 공간에 백업해두고 실제 레코드 값을 변경한다.
백업된 데이터는 불필요하다고 판단하는 시점에 주기적으로 삭제한다.
Undo에 백업된 레코드가 많아지면 MySQL 서버의 처리 성능이 떨어질 수 있다.
이러한 변경방식은 MVCC(Multi Version Concurrency Control)라고 부른다.

문제

  • PHANTOM READ
    다른 트랜잭션에서 수행한 변경 작업에 의해 레코드가 보였다가 안 보였다가 하는 현상
    이를 방지하기 위해서는 쓰기 잠금을 걸어야 한다.

SERIALIZABLE

가장 단순한 격리 수준이지만 가장 엄격한 격리 수준
성능 측면에서는 동시 처리성능이 가장 낮다.
SERIALIZABLE에서는 PHANTOM READ가 발생하지 않는다.하지만 데이터베이스에서 거의 사용되지 않는다

0개의 댓글