현재 선택한 정보처리 과정

정보처리기사 필기 이론 학습

이론 목록으로 돌아가기

트랜잭션·격리 수준·락·교착상태

트랜잭션은 원자성·일관성·격리성·지속성을 만족하도록 관리하는 논리적 작업 단위다. 동시 실행에서는 직렬 가능성과 더티·비반복·팬텀 읽기, 갱신 유실을 구분한다. 격리 수준은 허용 현상을 정하고 잠금·타임스탬프·검증·다중 버전은 병행 제어 방법이다. 2단계 로킹과 분산 2단계 커밋은 목적이 다르며 교착은 대기 관계의 순환을 확인해 처리한다.

예상 읽기 12

트랜잭션과 동시성 제어의 목표

트랜잭션(Transaction)은 데이터베이스의 상태를 하나의 일관된 상태에서 다른 일관된 상태로 바꾸는 논리적 작업 단위다. 여러 SQL 문장이 포함될 수 있으며, 전체가 성공하면 확정하고 어느 단계에서든 업무를 보장할 수 없으면 취소한다.

트랜잭션 제어의 핵심은 두 가지다.

  1. 오류가 발생해도 작업의 일부만 남지 않게 한다.
  2. 여러 트랜잭션이 동시에 실행되어도 허용되지 않은 결과가 나오지 않게 한다.

COMMIT, ROLLBACK, SAVEPOINT의 구문과 저장 프로그램 안에서의 사용은 SQL 응용 이론에서 다룬다. 여기서는 ACID, 실행 일정, 격리 수준, 잠금, MVCC와 교착상태를 중심으로 동시성 제어 원리를 설명한다.

ACID: 트랜잭션의 네 가지 성질

성질핵심 의미계좌 이체에서의 판단자주 틀리는 경계
원자성(Atomicity)트랜잭션의 작업을 전부 반영하거나 전부 취소한다.출금·입금·이체 기록이 모두 성공하거나 모두 취소되어야 한다.문장 하나의 성공과 트랜잭션 전체의 커밋은 같은 상태가 아니다.
일관성(Consistency)정의된 제약조건과 업무 불변식을 지키며 유효한 상태에서 유효한 상태로 이동한다.이체 전후의 전체 금액이 보존되고 잔액 규칙을 만족해야 한다.DBMS가 모든 업무 규칙을 자동으로 알아내는 것은 아니다.
격리성(Isolation)동시 실행의 중간 효과가 다른 트랜잭션의 올바른 결과를 깨뜨리지 않게 한다.두 이체가 동시에 실행되어도 허용되지 않은 잔액이 나오지 않아야 한다.모든 격리 수준이 실제로 트랜잭션을 한 개씩 순차 실행하는 것은 아니다.
지속성(Durability)커밋이 성공한 변경은 장애 뒤에도 해당 DBMS의 지속성 보장에 따라 복구되어야 한다.커밋된 이체가 시스템 재시작 후 사라지지 않아야 한다.지속성은 백업과 같은 뜻이 아니며, 미커밋 변경을 영구 보존한다는 뜻도 아니다.

원자성과 일관성은 서로 다르다

초기 잔액이 A 계좌 100, B 계좌 100이라고 하자. A에서 B로 30을 이체하면 정상 결과는 A=70, B=130이다.

  • A에서 30만 빼고 B에 넣지 않았다면 원자성 위반이다.
  • A=70, B=130으로 모두 반영되었더라도 업무 규칙이 “A의 최소 잔액은 80”이라면 일관성 위반이다.

원자성은 작업의 전부 또는 전무, 일관성은 작업 전후에 지켜야 할 유효 상태와 불변식의 문제다.

일관성은 DBMS와 애플리케이션이 함께 책임진다

기본키·외래키·CHECK·NOT NULL 같은 선언적 제약은 DBMS가 검사할 수 있다. 그러나 “한 부서에는 승인자 한 명 이상이 있어야 한다”처럼 여러 행과 업무 흐름을 함께 보는 규칙은 스키마, 트랜잭션 설계, 격리 수준과 애플리케이션 검증을 결합해야 할 수 있다.

트랜잭션 상태

상태의미
활동(Active)연산 수행 중
부분 완료(Partially Committed)마지막 연산은 끝났지만 커밋 확정 전
커밋(Committed)성공이 확정됨
실패(Failed)정상 진행이 불가능함
철회(Aborted)변경 효과를 취소한 상태
CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
활동 → 부분 완료 → 커밋 → 종료
활동 또는 부분 완료 → 실패 → 철회 → 종료 또는 재시작

마지막 SQL이 성공했다는 것과 커밋이 확정되었다는 것은 다르다. 실패는 아직 취소 처리 중일 수 있는 상태이고 철회는 취소가 완료된 상태다.

좌우로 이동해 그림을 확인하세요.그림 크게 보기
트랜잭션의 상태 전이
트랜잭션의 상태 전이

트랜잭션의 상태 전이

활동 → 부분 완료 → 커밋이 정상 경로다. 활동 또는 부분 완료 중 실패하면 실패 → 철회로 진행하고 재시작 또는 종료한다. 마지막 SQL의 성공은 지속성이 확보된 커밋과 다르다.

실행 일정과 직렬 가능성

일정(Schedule)은 여러 트랜잭션의 읽기·쓰기·커밋 연산을 시간순으로 나열한 것이다. r1(X)는 T1의 읽기, w1(X)는 쓰기를 나타낸다.

구분판별 기준
직렬 일정한 트랜잭션이 끝난 뒤 다음 트랜잭션 실행
비직렬 일정여러 트랜잭션의 연산이 섞임
직렬 가능 일정어떤 직렬 실행과 동등한 효과를 갖는 일정

서로 다른 트랜잭션이 같은 항목에 접근하고 적어도 하나가 쓰기이면 충돌한다. 읽기끼리는 충돌하지 않는다.

선행 그래프는 먼저 실행된 충돌 연산의 트랜잭션에서 나중 트랜잭션으로 간선을 그린다. 순환이 없으면 충돌 직렬 가능하다. A에서는 T1이 먼저 쓰고 B에서는 T2가 먼저 쓰면 T1 → T2 → T1 순환이 생길 수 있다.

대기 그래프는 현재 자원 해제를 기다리는 관계로 교착상태를 판별한다. 두 그래프는 간선의 의미가 다르다. 직렬 가능성이 물리적으로 트랜잭션 하나씩 실행한다는 뜻도 아니다.

동시 실행에서 발생하는 대표 이상 현상

더티 읽기

더티 읽기(Dirty Read, 오손 읽기)는 한 트랜잭션이 다른 트랜잭션의 미커밋 값을 읽는 현상이다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
초기 X = 100
T1: w1(X = 120)
T2: r2(X) → 120을 사용
T1: a1      → 120은 취소됨

T2는 최종적으로 확정되지 않은 값에 근거해 계산했을 수 있다.

비반복 읽기

비반복 읽기(Nonrepeatable Read)는 한 트랜잭션이 같은 행을 다시 읽었을 때, 다른 트랜잭션이 그 행을 수정하거나 삭제하고 커밋하여 값이 달라지는 현상이다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
T1: r1(X) → 100
T2: w2(X = 120), c2
T1: r1(X) → 120

대상은 주로 같은 행의 값이다.

팬텀 읽기

팬텀 읽기(Phantom Read)는 한 트랜잭션이 같은 검색 조건의 질의를 다시 실행했을 때, 다른 트랜잭션의 삽입·삭제 또는 조건 경계를 넘는 갱신 때문에 결과 행 집합이 달라지는 현상이다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
T1: WHERE salary >= 5000 → 3행
T2: salary 5500인 행 INSERT, COMMIT
T1: 같은 조건 재조회       → 4행

비반복 읽기는 기존 행의 값 변화에 초점을 두고, 팬텀 읽기는 조건을 만족하는 행 집합의 변화에 초점을 둔다.

갱신 유실

갱신 유실(Lost Update)은 둘 이상의 트랜잭션이 같은 이전 값을 읽고 각각 계산한 결과를 기록하여, 나중 쓰기가 앞선 쓰기를 덮어쓰는 현상이다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
초기 재고 = 10
T1: 재고 10 읽음 → 2개 판매 계산 → 8 기록
T2: 재고 10 읽음 → 3개 판매 계산 → 7 기록
최종 재고 = 7
정상 기대값 = 5

더티 읽기·비반복 읽기·팬텀 읽기의 고전적 표와 별도로 다루는 현상이며, 실제 방지·탐지 방식은 DBMS와 SQL 작성 방식에 따라 다르다.

SQL 표준의 네 가지 격리 수준

격리 수준(Isolation Level)은 동시성과 일관성 사이에서 어떤 현상을 허용할지 정한다. 다음 표는 SQL 표준이 요구하는 최소 보장을 시험 관점에서 요약한 것이다.

격리 수준더티 읽기비반복 읽기팬텀 읽기
READ UNCOMMITTED발생 가능발생 가능발생 가능
READ COMMITTED방지발생 가능발생 가능
REPEATABLE READ방지방지발생 가능
SERIALIZABLE방지방지방지

여기서 “발생 가능”은 반드시 발생한다는 뜻이 아니다. DBMS가 표준의 최소 보장보다 더 강하게 구현할 수 있다.

수준별 핵심 해석

  • READ UNCOMMITTED: 미커밋 변경을 읽을 수 있는 가장 낮은 표준 수준이다.
  • READ COMMITTED: 각 문장은 커밋된 데이터만 읽지만, 같은 트랜잭션의 다음 문장이 더 최근 커밋을 볼 수 있다.
  • REPEATABLE READ: 한 번 읽은 행을 다시 읽을 때 같은 값을 유지하도록 보장한다. 표준상 팬텀은 허용될 수 있다.
  • SERIALIZABLE: 성공적으로 커밋된 동시 트랜잭션들의 효과가 어떤 직렬 실행 순서와 같아야 한다.

SERIALIZABLE이 모든 트랜잭션을 물리적으로 한 줄로 세워 실행한다는 뜻은 아니다. 잠금, 범위·술어 보호, 버전 검증 등으로 동시에 실행한 뒤 직렬 순서와 동등하지 않은 경우 한 트랜잭션을 중단할 수 있다.

이 표는 표준의 최소 보장이다. 특정 제품은 같은 이름의 수준을 더 강하게 구현할 수 있으므로 제품 전제가 있는 문제는 그 설명을 따른다.

잠금: 충돌 접근을 기다리게 하는 비관적 제어

잠금(Lock)은 트랜잭션이 데이터나 객체에 특정 접근 권한을 확보하고, 호환되지 않는 다른 접근을 기다리게 하는 동시성 제어 수단이다.

공유 락과 배타 락

개념적인 S/X 호환성은 다음과 같다.

요청 락 \ 보유 락공유 S배타 X
공유 S호환대기
배타 X대기대기
  • 공유 락(Shared Lock, S): 읽기 목적의 잠금이다. 여러 트랜잭션이 같은 항목에 공유 락을 함께 가질 수 있다.
  • 배타 락(Exclusive Lock, X): 쓰기 목적의 잠금이다. 다른 트랜잭션의 공유·배타 접근과 충돌한다.

이 표는 잠금 기반 병행 제어의 기본 개념이다. MVCC를 사용하는 DBMS에서는 일반 SELECT가 행 수준 공유 락을 얻지 않고 과거 커밋 버전을 읽을 수 있으므로, 모든 제품의 실제 잠금 모드를 이 두 종류로만 단정하면 안 된다.

잠금 단위와 절충 관계

잠금 단위장점비용·위험
서로 다른 행의 동시 접근이 쉬움잠금 수와 관리 오버헤드가 커질 수 있음
페이지·블록행보다 잠금 수가 적음같은 페이지의 무관한 행도 함께 막힐 수 있음
테이블잠금 관리가 단순함동시성이 크게 낮아질 수 있음
데이터베이스·스키마 등 상위 객체구조 변경이나 관리 작업을 넓게 보호영향 범위가 매우 큼

작은 단위가 항상 빠르거나 큰 단위가 항상 나쁜 것은 아니다. 충돌 빈도, 접근 범위, 잠금 수와 제품의 비용 모델을 함께 봐야 한다.

2단계 로킹과 다른 병행 제어 방식

2단계 로킹(2PL)은 락의 획득·해제 순서를 두 단계로 제한한다.

단계허용금지
확장 단계새 락 획득락 해제
축소 단계락 해제새 락 획득

첫 락을 해제한 뒤 새 락을 얻으면 기본 2PL 규칙을 위반한다. 2PL은 충돌 직렬 가능성을 보장하지만 교착상태까지 막는 것은 아니다. 시작 전에 필요한 모든 락을 동시에 확보하는 보수적 방식과도 구분한다.

다른 대표 병행 제어 방식은 다음과 같다.

방식핵심 원리
타임스탬프 순서트랜잭션에 부여한 시간 순서에 맞추어 충돌 연산을 제어
낙관적 검증충돌이 적다고 가정해 작업한 후 커밋 전 검증하고 충돌 시 취소
다중 버전(MVCC)여러 버전 중 허용된 일관된 버전을 읽게 함

MVCC는 격리 수준 이름이 아니며 모든 쓰기 잠금과 충돌을 없애는 것도 아니다. 잠금은 대기로, 낙관적 방식은 사후 검증·취소로 충돌을 처리하는 기본 차이를 이해한다.

2단계 커밋과의 구분

2단계 커밋(2PC)은 여러 사이트의 트랜잭션 완료를 조정한다. 준비 단계에서 참여 사이트들이 커밋 가능한지 응답하고, 결정 단계에서 조정자가 전체 커밋 또는 취소 결정을 전달한다. 장애 시 결정 대기가 생길 수 있다.

2PL은 락 획득·해제와 동시성 제어, 2PC는 분산 트랜잭션의 완료 결정이다. 같은 '2단계'라는 이름만으로 혼동하지 않는다.

교착상태와 대기 그래프

T1이 A를 잠근 채 B를 기다리고 T2가 B를 잠근 채 A를 기다리면 서로 진행하지 못한다. 이를 교착상태라고 한다. 대기 그래프의 T1 → T2는 T1이 T2의 자원 해제를 기다린다는 뜻이다. T1 → T2 → T1의 순환은 이 예에서 교착상태를 나타낸다.

교착상태에는 상호 배제, 점유와 대기, 비선점, 순환 대기의 네 필요 조건이 있다. 그중 하나를 방지하면 교착을 예방할 수 있다.

대응핵심
예방자원을 항상 같은 순서로 요청하는 등 필요 조건을 차단
탐지실제 대기 관계에서 순환 등을 확인
회복희생 트랜잭션을 취소해 자원을 해제

작업 범위와 트랜잭션을 짧게 하는 것은 충돌 가능성을 줄이지만 그 자체로 모든 교착을 수학적으로 배제하지는 않는다. 타임아웃은 오래 기다렸다는 뜻이지 교착의 확정 증거는 아니다.

단순 대기는 락 보유자가 완료하면 진행할 수 있고, 교착은 순환 때문에 개입이 필요하다. 기아는 특정 트랜잭션이 계속 뒤로 밀려 자원을 얻지 못하는 현상이다. 일정의 직렬 가능성을 보는 선행 그래프와 현재 자원 대기를 보는 대기 그래프의 간선 의미도 구분한다.

좌우로 이동해 그림을 확인하세요.그림 크게 보기
대기 그래프로 교착상태 판별
대기 그래프로 교착상태 판별

대기 그래프로 교착상태 판별

T1이 A를 보유하고 B를, T2가 B를 보유하고 A를 기다리면 T1→T2→T1 순환으로 교착상태가 된다. 화살표는 기다리는 쪽에서 보유한 쪽으로 향한다. T1→T2만 있고 T2가 진행 가능하면 단순 대기다. 선행 그래프와 대기 그래프는 목적이 다르다.

병행 제어 방식과 이상 현상의 판별

기본 2단계 로킹은 락을 얻는 확장 단계와 락을 해제하는 축소 단계로 나뉜다. 한 번 락을 해제해 축소 단계에 들어간 뒤 새로운 락을 얻으면 기본 2PL 규칙을 위반한다. 기본 2PL은 충돌 직렬 가능성을 보장하지만 교착상태를 자동으로 없애지는 않는다.

낙관적 병행 제어는 충돌 가능성이 낮다고 보고 작업한 뒤 검증 단계에서 충돌을 확인한다. 충돌을 발견하면 취소·재시도가 필요할 수 있다. 타임스탬프 순서 제어는 부여된 시각·순서 정보로 충돌 작업이 허용되는 순서를 판단한다. MVCC, 잠금, 낙관적 검증을 같은 명칭의 기법으로 혼용하지 않는다.

잠금 단위가 작으면 서로 다른 행에 대한 병행성이 높아질 수 있지만 더 많은 잠금을 관리한다. 단위가 크면 관리 비용은 줄 수 있으나 직접 관련 없는 행의 작업도 기다리게 할 수 있다.

초기 값 100을 두 트랜잭션이 각각 읽고 10·20을 차감하여 90·80을 덮어쓰면, 직렬 처리에서의 기대값 70 대신 80이 남을 수 있다. 이는 갱신 유실이다. 다른 트랜잭션이 아직 커밋하지 않은 150을 읽었는데 작성자가 롤백해 100으로 돌아갔다면 더티 읽기다. 값이 바뀌었다는 사실만이 아니라 누가 언제 읽고 쓰고 커밋했는지를 추적한다.

선행 그래프는 서로 다른 트랜잭션이 같은 항목에 접근하고 하나 이상이 쓰기일 때 실제 선후 관계로 간선을 만든다. w1(A), r2(A), w2(B), r1(B)는 T1→T2와 T2→T1을 모두 만들므로 충돌 직렬 가능하지 않다. 교착상태의 대기 그래프와 같은 그래프로 해석하지 않는다.