1. 트랜잭션 개요
1.1. 트랜잭션
- 트랜잭션(Transaction)의 정의
- 데이터베이스의 상태를 변화시키기 위해 수행하는 작업의 논리적인 단위이다.
- 여러 개의 SQL 연산(INSERT, UPDATE 등)이 모여 하나의 트랜잭션을 구성하며, 이들은 모두 성공하거나 모두 실패해야 한다. (All or Nothing)
1.2. 트랜잭션의 4가지 특성 (ACID)
-
원자성(Atomicity)
- 트랜잭션 내의 연산은 모두 반영되거나, 전혀 반영되지 않아야 한다.
- (완료되지 않으면
ROLLBACK)
-
일관성(Consistency)
- 트랜잭션 수행 전후에 데이터베이스는 일관된 상태(제약조건 만족 등)를 유지해야 한다.
- 수행 도중에는 일시적으로 불일치할 수 있다.
-
고립성(Isolation)
- 현재 수행 중인 트랜잭션이 완료될 때까지 다른 트랜잭션이 중간 연산 결과에 접근할 수 없다.
-
지속성(Durability)
- 성공적으로 완료(Commit)된 트랜잭션의 결과는 시스템 장애가 발생하더라도 영구적으로 보존되어야 한다.
| 특성 | 의미 | 동시성 제어 | 회복 |
|---|---|---|---|
| 원자성(Atomicity) | 트랜잭션 내 모든 연산은 수행되거나 수행되지 않음 | - | O |
| 일관성(Consistency) | 트랜잭션 전/후의 데이터베이스 상태는 항상 일관성 있음 | O | - |
| 고립성(Isolation) | 동시에 실행되는 트랜잭션은 서로 독립적임 | O | - |
| 지속성(Durability) | 완료된 트랜잭션은 데이터베이스에 영구적으로 반영됨 | - | O |
1.3. 연산 종류
- COMMIT: 트랜잭션의 변경 내용을 DB에 영구 반영하고 완료함.
- ROLLBACK: 트랜잭션의 변경 내용을 취소하고 수행 전 상태로 되돌림(원자성 보장).
2. 동시성 제어
- 동시성 제어(Concurrency Control)의 필요성
- 다수의 사용자가 동시에 DB에 접근할 때, 트랜잭션 간의 간섭으로 인해 부정확한 결과가 생기지 않도록 제어하는 기법이다.
2.1. 동시성 제어가 없을 때 발생하는 문제
-
갱신 손실(lost update)
- 두 트랜잭션이 같은 데이터를 동시에 갱신할 때,
- 나중의 갱신이 먼저의 갱신을 덮어써서 손실되는 현상
-
오손 읽기(dirty read)
- 한 트랜잭션의 커밋되지 않은 데이터를 다른 트랜잭션이 읽는 현상
- → READ COMMITTED 고립 수준에서 불가능
-
반복 불가능한 읽기(non-repeatable read)
- 한 트랜잭션이 같은 데이터를 두 번 읽을 때,
- 그 사이에 다른 트랜잭션이 값을 갱신하여 다른 값을 읽는 현상
- → REPEATABLE READ 고립 수준에서 불가능
-
유령 읽기(phantom read)
- 한 트랜잭션 내에서 범위 쿼리를 반복 수행할 때,
- 다른 트랜잭션의 삽입(INSERT)으로 인해 없던 데이터가 나타나는 현상
- → SERIALIZABLE 고립 수준에서 불가능
2.2. 제어 기법: 로킹(Locking)
-
로크의 종류
- Shared-lock (S-lock; 공유 로크)
- 읽기(Read) 목적
- 다른 공유 로크와 양립 가능
- Exclusive-lock (X-lock; 독점 로크)
- 갱신(Write) 목적
- 다른 어떤 로크와도 양립 불가(상호 배제)
- Shared-lock (S-lock; 공유 로크)
-
2단계 로킹 프로토콜 (2PL; 2-phase locking)
- 확장 단계: 로크를 얻기만 하고 해제는 하지 않음
- 수축 단계: 로크를 해제하기만 하고 새로운 로크는 얻지 않음
- 특징: 직렬 가능성을 보장하지만 교착상태(Deadlock)가 발생할 수 있음
2.3 다중 로크 단위(Multiple Granularity)
- DB, 테이블, 블록, 튜플 등 로크를 거는 단위의 크기를 조절한다.
- 단위가 작을수록 병행성(동시성)은 증가하지만, 오버헤드가 커진다.
- 단위가 클수록 병행성은 감소하지만, 오버헤드는 줄어든다.
3. 회복
3.1. 회복
-
회복(Recovery)의 개념
- 장애(시스템 다운, 디스크 오류 등) 발생 시 데이터베이스를 일관성 있는 상태로 복구하는 기법이다.
-
회복을 위한 데이터베이스 사본
- 로그(Log): 변경 연산 기록을 별도의 파일에 유지하여 회복에 사용한다.
- 덤프(Dump): 데이터베이스 전체를 주기적으로 복사한다.
3.2. 회복 기법
-
회복을 위한 연산
- UNDO(취소) - 원자성 보장
- 장애 발생 시점까지 완료되지 않은 트랜잭션의 변경 내용을 취소
- REDO(재수행) - 지속성 보장
- 장애 발생 전 완료(Commit)된 트랜잭션의 내용을 로그를 이용해 다시 실행
- UNDO(취소) - 원자성 보장
-
로그 레코드의 유형
[Trans-ID, start]- 한 트랜잭션이 생성될 때 기록되는 로그 레코드
[Trans-ID, X, old_value, new_value]- 주어진 Trans_ID를 갖는 트랜잭션이
- 데이터 항목 X를 이전값(old_value)에서 새값(new_value)로 수정했음을 나타내는 로그 레코드
[Trans-ID, commit]- 주어진 Trans_ID를 갖는 트랜잭션이
- 데이터베이스에 대한 갱신을 모두 성공적으로 완료하였음을 나타내는 로그 레코드
[Trans-ID, abort]- 주어진 Trans_ID를 갖는 트랜잭션이 철회되었음을 나타내는 로그 레코드
-
로그 회복 기법
- 즉시 갱신(Immediate Update)
- 수행 중 변경 내용을 즉시 DB와 로그에 반영
- COMMIT 전 장애 시 UNDO 수행
- COMMIT 후 장애 시 REDO 수행
- 지연 갱신(Deferred Update)
- COMMIT 전까지는 로그에만 기록하고 DB 반영을 지연
- 장애 시 REDO만 수행 (UNDO 불필요)
- 즉시 갱신(Immediate Update)
3.3. 체크포인트
-
로그 먼저 쓰기(WAL; Write-Ahead Logging)
- 로그 버퍼를 데이터베이스 버퍼보다 먼저 디스크에 기록해야 함 (시스템 다운 대비)
-
체크포인트(Checkpoint)
- 주기적으로 주기억장치(버퍼)의 내용을 디스크에 강제로 기록하고 로그와 동기화하는 시점
- 회복 시 체크포인트 이후의 로그만 처리하면 되므로 회복 시간을 단축시킨다.
-
체크포인트를 할 때 수행되는 작업
- 주기억 장치의 로그 버퍼를 디스크에 강제로 출력
- 주기억 장치의 데이터베이스 버퍼를 디스크에 강제로 출력
- checkpoint 로그 레코드를 로그 버퍼에 기록한 후 디스크에 강제로 출력
4. PL/SQL의 트랜잭션
4.1. 트랜잭션 제어 명령어(TCL)
- COMMIT: 변경 사항 저장 및 트랜잭션 종료
- ROLLBACK: 변경 사항 전체 취소 및 트랜잭션 종료
- SAVEPOINT: 트랜잭션 내 중간 저장점 설정
- ROLLBACK TO SAVEPOINT: 특정 저장점까지만 부분적으로 취소
4.2. 고립 수준(Isolation Level)
SQL 표준 및 오라클에서 제공하는 트랜잭션 고립 수준에 따라 발생 가능한 문제가 다르다.
| 고립 수준 (Level) | 오손 데이터 읽기 (Dirty Read) | 반복 불가 읽기 (Unrepeatable Read) | 팬텀 문제 (Phantom Read) |
|---|---|---|---|
| READ UNCOMMITTED | 가능 | 가능 | 가능 |
| READ COMMITTED | 불가능 | 가능 | 가능 |
| REPEATABLE READ | 불가능 | 불가능 | 가능 |
| SERIALIZABLE | 불가능 | 불가능 | 불가능 |
- READ COMMITTED: 오라클의 기본 설정이다.
- SERIALIZABLE: 가장 높은 수준으로 완벽한 일관성을 제공하지만 동시성이 가장 낮다.
- SET TRANSACTION READ ONLY: 읽기 전용 트랜잭션으로 설정하여 DBMS의 동시성 처리 성능을 높일 수 있다.