방송대 데이터베이스시스템 - 14강. 회복 시스템
1. 회복 시스템
회복의 역할
예상치 못한 HW 고장 및 SW 오류가 발생하면 사용자의 작업에 대한 안정적 디스크 반영 여부 보장이 불가능
오류 발생 이전의 일관된 상태로 데이터베이스를 복원시키는 기법이 요구
회복 시스템(recovery system)
- 정상적으로 운영되고 있는 동안 데이터베이스 회복에 필요한 데이터를 별도 보관하다가 DBMS에 문제 발생 시 시스템 내에서 발생한 실패의 원인을 검출하고 실패 이전의 일관적인 상태로 되돌리는 작업을 할 때 이 데이터를 사용하는 것
- 시스템 내의 고장 원인 검출, DBMS의 안정성 및 신뢰성을 보장
데이터베이스는 데이터 복원 절차 내재화
시스템 실패(system failure)의 유형
트랜잭션 실패 | • 논리적 : 잘못된 데이터 입력이나 부재, 버퍼 오버플로(메모리 초과), 자원 초과 이용 • 시스템적 : 운용 시스템의 교착상태 |
시스템 장애 | 시스템의 하드웨어 고장, 소프트웨어의 오류 주기억장치와 같은 휘발성 저장장치의 내용 손실 |
디스크 실패 | 비휘발성 디스크 저장장치의 손상 및 고장으로 인한 데이터 손실 |
회복 데이터의 구성
장애 발점 이전 시점의 일관된 상태로 복원시키는 근본원리는 일부 또는 전체 데이터를 복제한 복사본을 구성하는 것
• 백업(backup) : 데이터베이스의 일부 또는 전체를 주기적으로 복제하는 방식
저장 방식 | 물리적 백업 | 데이터베이스 내의 데이터 원본 파일들을 직접 복사하는 백업 신속하게 복구되어야 하는 데이터베이스의 경우 적합함. |
논리적 백업 | 데이터베이스의 구조를 형성시키는 SQL 명령집합으로 구성됨. 시간이 오래 걸리 수 있으나 물리적 환경이 다른 시스템 상에서도 적용시킬 수 있음. |
|
서버 상태 | 온라인 백업 | 데이터베이스가 정상적으로 동작하는 중간에 실행되는 백업 사용자들은 온라인 백업 중에도 데이터베이스에 접근할 수 있음. |
오프라인 백업 | 데이터베이스가 동작을 멈춘 상태에서 실행되는 백업 오프라인 백업 중에는 사용자들이 데이터베이스에 접근할 수 없음. |
|
백업 대상 | 전체 백업 | 데이터베이스 전체를 모두 백업하는 작업 많은 시간이 소요되고, 복제본의 용량이 많이 필요한 점 등을 고려해야함. |
증분 백업 | 전체 백업 이후 주어진 시간 동안 이루어진 변화(증분)만을 복제하는 백업 | |
저장 장소 | 로컬 백업 | 백업을 수행하는 컴퓨터에 설치되어 있는 DBMS를 백업하는 방식 |
원격 백업 | 원격으로 연결된 DBMS를 백업하는 방식 |
• 로그(log)
- 데이터 변경 이전과 이후의 값을 별도의 파일에 기록하는 방식 (≒ 장부)
- 디버깅과 오류분석, 시스템 모니터링, 보안 감시, 성능 분석 등에 사용됨.
데이터 저장 구조
데이터는 디스크와 같은 비휘발성 저장장치에 저장되며, 전체 데이터의 일부만 주기억장치(휘발성)에 상주함.
데이터베이스는 데이터를 블럭(block) 단위로 전송하고, 기억장소를 분할
트랜잭션은 디스크로부터 주기억장치로 데이터를 가져오며, 변경된 데이터는 다시 디스크에 반영됨.
· 가져오기, 내보내기 연산은 블럭 단위로 실행
· 물리적 블록 : 디스크 상의 블럭
· 버퍼 블록 : 주기억장치(메인 메모리)에 임의적으로 상주하는 블럭
메인 메모리와 디스크 사이의 연산
Input(X) | 물리적 블록(디스크 상의 블록) X를 메인 메모리에 적재 |
Output(Y) | 버퍼블록(메인메모리) Y를 디스크에 저장 |
Read(X) | 특정 트랜잭션에서 데이터 X를 메인 메모리로부터 읽어들이는 작업 메인메모리에 있는 데이터블럭이 트랜잭션이 사용하는 고유의 데이터 영역으로 읽혀지는 과정 버퍼블럭 X가 메인 메모리에 없을 경우 Input(X)를 수행 |
Write(Y) | 특정 트랜잭션에서 데이터 Y를 메인 메모리에 쓰는(저장하는) 작업 트랜잭션이 사용하는 메모리 공간에서 메인 메모리가 사용항는 메모리 공가능로 데이터가 기록되는 과정 버퍼블럭 Y가 메인 메모리에 없을 경우 Input(Y)를 수행 (→ Write(Y) 실행을 위한 첫 번째 단계) |
· 일반적으로 Read(X)와 Write(Y) 연산은 버퍼의 상황에 따라 디스크로부터 메인 메모리로 블록 전송 명령인 Input(X)를 요구하지만 Output(X)를 요구하지는 않음.
→ 즉, 데이터를 디스크에서 읽어오는 작업(Input)은 주로 필요한 데이터를 메인 메모리로 가져오기 위해 수행되며, 데이터를 디스크에 기록하는 작업(Output)은 필요한 경우에 수행됨.
· 여러 트랜잭션이 메인 메모리 버퍼 내의 동일한 데이터 항목을 수정한 후에 디스크에 기록하도록 디스크 쓰기를 최대한 지연시킴으로써 DBMS의 성능을 향상시킴.
디스크 I/O 비용 절감 | 디스크로의 쓰기 작업은 비용이 많이 드는 작업임. 버퍼를 활용하여 여러 트랜잭션이 수정한 데이터를 한꺼번에 디스크에 기록하면 디스크 I/O 비용 절감 가능 |
일괄 처리와 최적화 | 데이터를 한꺼번에 기록하면 일괄 처리로 데이터 처리 가능 디스크 접근을 최소화하고 성능을 향상시킬 수 있음. |
트랜잭션 격리 수준 유지 | 각 트랜잭션이 독립적으로 데이터를 수정할 수 있어 트랜잭션 격리 수준을 유지할 수 있음. |
2. 로그 기반 회복
로그 기반 회복
데이터베이스가 수행한 모든 수정 작업을 기록한 여러 종류의 로그를 사용하여 회복하는 시스템
로그 레코드
< Ti, Xj, V1, V2 > | Ti가 데이터 항목 변경 연산을 수행하여 Xj의 값을 V1에서 V2로 변경 |
< Ti, start > | Ti가 시작, 트랜잭션이 시작되는 시점 |
< Ti, commit > | Ti가 커밋, 트랜잭션이 완료되고 데이터베이스에 변경 사항을 반영하는 시점 (안정적으로 저장 완료) |
< Ti, abort > | Ti가 취소 (문제가 있다는 지적, 취소 후 롤백 작업을 함) |
데이터 항목 변경 과정
WAL (Write-Ahead Log) : 트랜잭션은 데이터베이스 수정 전, 로그 레코드를 생성하여 기록
ex. 잔액이 10만 원인 계좌에서 5만원을 입금하는 경우
- 우선 들어온 5만 원을 입금 시킨 후 잔액 기록을 15만 원으로 변경함. (DB 수정 → 로그 기록)
→ 입금 시킨 후 오류가 난 경우 기록이 남지 않으므로 데이터 원복이 불가능함.
- 잔액 기록을 15만 원으로 변경한 후, 들어온 5만 원을 입금 시킴. (로그 기록 → DB 수정)
→ 로그 기록 후 반영이 안 된 경우 오류 발생 이전으로 원복 가능함.
데이터 항목 변경 과정
· 트랜잭션이 메인 메모리의 개인 영역에서 여러 연산을 수행
· 트랜잭션이 데이터 항목에 존재하는 메인 메모리에 위치한 버퍼 블럭의 데이터를 변경
· Output 명령을 실행하여 버퍼 블럭을 디스크에 기록
Redo와 Undo 연산
회복 기법은 로그에 대해 두 연산을 사용
Redo(Ti) | 트랜잭션의 변경 작업을 다시 수행하는 것 (다시하기) Ti에 의하여 수정된 새로운 값으로 데이터베이스의 데이터 항목값을 수정 시스템 장애 또는 비정상적인 종료로 인해 일부 트랜잭션의 변경 작업이 디스크에 반영되지 않은 경우 → Redo 작업을 통해 이러한 변경 작업을 다시 디스크에 기록하여 데이터 일관성을 복구 |
Undo(Ti) | 트랜잭션의 변경 작업을 취소하고 이전 상태로 되돌리는 것 (되돌리기) Ti에 의해 수정된 모든 데이터 항목을 이전 값으로 복귀, 완료 후 <Ti, abort> 기록 트랜잭션이 실패하거나 롤백 명령을 받은 경우 → Undo 작업을 통해 해당 트랜잭션의 변경 작업을 취소하고 이전 상태로 복원 |
시스템 장애 발생 시
· 로그에 <Ti, start>가 있지만 <Ti, commit> 또는 <Ti, abort>를 포함하지 않는 경우 : Ti를 Undo
- 작업이 메모리에서만 발생 O, 디스크에 반영 X
- 디스크 반영 상 오류가 난 것이므로 이미 사용자에게는 작업이 완료되었다고 결과가 전달된 상태
· 로그에 <Ti, start>가 있고 <Ti, commit> 또는 <Ti, abort>를 포함하는 경우 : Ti를 Redo
- 작업이 메모리에서 발생 O, 디스크에 반영 O
- 트랜잭션이 실행되는 도중에 DB에서 오류가 난 것임.
데이터베이스 변경과 커밋
데이터베이스 변경 시 복구 알고리즘의 고려 사항
· 메모리(O), 디스크(X) : 트랜잭션의 일부 변경 사항이 버퍼 블록에만 반영되고 물리 블록에 기록되지 않은 상태에서 트랜잭션이 커밋되는 상황
· 메모리(O), 디스크(O) : 트랜잭션이 동작 상태에서 데이터베이스를 수정했으나 수정 후에 발생한 실패로 취소가 필요한 상황
트랜잭션 커밋 상황
· <Ti, commit> 로그 레코드가 안정된 저장장치에 기록 완료 시 (레코드 O) → 트랜잭션 커밋으로 간주
· <Ti, commit> 로그 레코드가 기록되기 전에 장애 발생 (레코드 X) → 롤백
회복의 유형
회복은 트랜잭션에 의해 요청된 갱신 작업이 디스크에 반영되는 시점에 따라 구분
지연 갱신 회복(deferred update restore)
- 부분 커밋까지 디스크 반영을 지연시키고 로그에만 기록 (성능 향상을 위해 디스크 접근 최소화)
- 실패 시, 별도의 회복 작업 필요 없이 로그만 수정
- Undo 작업이 필요 없으며, 커밋 로그가 있는 트랜잭션에 대해서만 Redo 연산 수행, <Ti, Xj, V2> 형식 사용
즉시 갱신 회복(immediate update restore)
- 갱신 요청을 곧바로 디스크에 반영
- 실패 시, 디스크에 반영된 갱신 내용을 로그를 바탕으로 회복
- Undo 연산을 반드시 수행해야 하며, <Ti, Xj, V1, V2> 형식 사용
상황 1 | 지연 갱신 회복 | 즉시 갱신 회복 |
![]() |
<T1, start>만 있고 <T1, commit> 또는 <T1, abort> 레코드가 없기 때문에 실제 데이터베이스에 반영된 내용이 없음. T1 로그 레코드만 삭제해줌. T2는 시작하지 않았으므로 어떠한 조치도 없음. |
<T1, start>만 있고 <T1, commit> 또는 <T1, abort> 레코드가 없지만, 일부분이 갱신 내용에 반영되었으므로 Undo(T1)을 수행함. A는 30,000원으로 복원됨. T2는 시작하지 않았으므로 어떠한 조치도 없음. |
상황 2 | 지연 갱신 회복 | 즉시 갱신 회복 |
![]() |
<T1, start>, <T1, commit> 또는 <T1, abort> 레코드가 있으므로 실제 데이터베이스에 반영된 내용이 있음. Redo(T1) 연산이 실행됨. <T2, start>만 있고 <T2, commit> 또는 <T2, abort> 레코드가 없기 때문에 실제 데이터베이스에 반영된 내용이 없음. T2에 대한 로그 레코드를 무시함. |
<T1, start>, <T1, commit> 또는 <T1, abort> 레코드가 있으므로 실제 데이터베이스에 반영된 내용이 있음. Redo(T1) 연산이 실행됨. <T2, start>만 있고 <T2, commit> 또는 <T2, abort> 레코드가 없기 때문에 Undo(T2) 연산이 수행됨. A, B, C 값을 25,000, 15,000, 50,000으로 복원 |
상황 3 | 지연 갱신 회복 | 즉시 갱신 회복 |
![]() |
<T1 commit>, <T2 commit> 로그 레코드가 안정 저장장치에 기록된 후 시스템 장애가 발생함. T1, T2의 갱신사항을 반영하기 위해 Redo(T1), Redo(T2)을 수행함. A, B, C 값을 25,000, 15,000, 40,000으로 복원 |
로그 기반 회복 시스템의 한계
로그의 크기는 시간이 지남에 따라 계속 증가하므로 대용량 로그의 탐색 비용이 매우 커짐.
Redo를 해야 하는 트랜잭션 중 대부분은 이미 데이터베이스에 반영됨.
반영된 트랜잭션의 재실행은 시스템 자원의 낭비임.
→ 체크포인트 기법 제안
체크포인트 기법
체크포인트 작업이 수행되는 동안 모든 수정 작업을 중단하며, 현재 시점에 메인 메모리의 버퍼 블록에 존재하는 모든 로그 레코드를 안정 저장장치로 기록
→ 체크포인트 수행 시점 이전의 로그 기록은 회복 시 데이터베이스 반영에 필요 없도록 만듦.
· 메인메모리에 존재하는 모든 로그 레코드를 안전 저장장치로 기록함.
· 수정된 모든 버퍼 블록을 Output하여 디스크에 반영함.
· 로그 레코드 <checkpoint ListT>를 안정한 저장장치에 기록
ListT : 체크포인트 시점에 실행 중인 트랜잭션 목록
체크포인트 기법을 이용한 회복 과정
· 로그의 마지막부터 역방향으로(최근부터) 탐색하여 <𝑐ℎ𝑒𝑐𝑘𝑝𝑜𝑖𝑛𝑡𝐿𝑖𝑠𝑡𝑇> 레코드를 찾음
· 𝐿𝑖𝑠𝑡𝑇에 존재하는 <𝑐ℎ𝑒𝑐𝑘𝑝𝑜𝑖𝑛𝑡𝐿𝑖𝑠𝑡𝑇> 이후에 실행된 트랜잭션에 대하여 Redo 와 Undo 연산만 수행
- 로그에 <𝑇𝑖,𝑐𝑜𝑚𝑚𝑖𝑡> 또는 <𝑇𝑖,𝑎𝑏𝑜𝑟𝑡>가 없는 𝐿𝑖𝑠𝑡𝑇안의 모든 트랜잭션을 Undo
- 로그에 <𝑇𝑖,𝑐𝑜𝑚𝑚𝑖𝑡> 또는 <𝑇𝑖,𝑎𝑏𝑜𝑟𝑡>가 있는 𝐿𝑖𝑠𝑡𝑇안의 모든 트랜잭션을 Redo
3. 회복 알고리즘
트랜잭션 롤백 알고리즘
1단계 : 로그를 역방향으로 탐색
2단계 : Ti의 로그 레코드 <Ti, Xj, V1, V2>에 대하여 (Undo)
- 데이터 항목 Xj에 V1 기록
- 로그 레코드 <Ti, Xj, V1>을 로그에 기록
3단계 : <Ti, start>를 찾은이후
- 역방향 탐색을 중단
- 로그 레코드 <Ti, abort>를 로그에 기록
롤백을 시킬 때마다 변경된 값으로 레코드가 일일이 다 기록됨.
시스템 장애 후 회복 알고리즘
시스템 장애 이후 재시작 시 다음 두 단계(Redo, Undo)를 거침
Redo 단계 (순방향) | Undo 단계 (역방향) |
· 최근의 체크포인트에서부터 순방향 로그 탐색 · 롤백 대상할 트랜잭션의 Undo 리스트인 𝐿𝑖𝑠𝑡𝑜𝑓𝑈𝑛𝑑𝑜를 𝐿𝑖𝑠𝑡𝑇로초기화 · <𝑇𝑖,𝑋𝑗,𝑉1,𝑉2>, <𝑇𝑖,𝑋𝑗,𝑉1> 형태의 모든 레코드를 재실행 · <𝑇𝑖,𝑠𝑡𝑎𝑟𝑡> 발견 시 , 𝑇𝑖를𝐿𝑖𝑠𝑡𝑜𝑓𝑈𝑛𝑑𝑜에 추가 · <𝑇𝑖,𝑎𝑏𝑜𝑟𝑡>, <𝑇𝑖,𝑐𝑜𝑚𝑚𝑖𝑡> 발견 시 𝑇𝑖를 Undo 리스트에서 제거 |
· 𝐿𝑖𝑠𝑡𝑜𝑓𝑈𝑛𝑑𝑜의 트랜잭션의 로그 레코드를 찾으면 트랜잭션 롤백 알고리즘 1 단계 수행 · 𝐿𝑖𝑠𝑡𝑜𝑓𝑈𝑛𝑑𝑜의 트랜잭션 𝑇𝑖에 대해 <𝑇𝑖,𝑠𝑡𝑎𝑟𝑡>를 만나면 로그에<𝑇𝑖,𝑎𝑏𝑜𝑟𝑡>를 기록하고 𝐿𝑖𝑠𝑡𝑜𝑓𝑈𝑛𝑑𝑜에서 제거 · 𝐿𝑖𝑠𝑡𝑜𝑓𝑈𝑛𝑑𝑜에 트랜잭션이 존재하지 않는 상태가 되면 Undo 단계를 종료 |
예시 1)
과거 | Redo 단계 (순방향) | Undo 단계 (역방향) |
< T0, start > | ||
< T0, B, 10000, 15000> | ||
< T1, start > | ||
< checkpoint {T0, T1} > | checkpoint에서 순방향으로 시작 (그 이전은 무시) Undolist : {T0, T1} |
|
< T1, C, 1000, 900 > | ||
< T1, commit > | T1을 Undolist에서 삭제 → T1을 Redo함. Undolist : {T0} |
|
< T2, start > | T2을 Undolist에 추가 Undolist : {T0, T2} |
< T2, abort> 레코드 추가, T2을 Undolist에서 삭제 Undolist : { } → Undo 단계 종료 |
< T2, A, 300, 500 > | < T2, A, 300 > | |
< T0, B, 10000 > | ||
< T0, abort> | T0을 Undolist에서 삭제 → T0을 Redo함. Undolist : {T2} |
|
현재 | < T2, A, 300 > < T2, abort> |
|
예시 2)
과거 | Redo 단계 (순방향) | Undo 단계 (역방향) |
< T0, start > | ||
< T0, A, 350, 300> | ||
< checkpoint {T0} > | checkpoint에서 순방향으로 시작 (그 이전은 무시) Undolist : {T0} |
|
< T1, start > | T1을 Undolist에 추가 Undolist : {T0, T1} |
|
< T1, C, 100, 50 > | ||
< T1, D, 0, 50 > | ||
< T1, commit > | T1을 Undolist에서 삭제 → T1을 Redo함. Undolist : {T0} |
|
< T2, start > | T2을 Undolist에 추가 Undolist : {T0, T2} |
< T2, abort> 레코드 추가, T2을 Undolist에서 삭제 Undolist : {T0} |
< T2, D, 50, 10 > | < T2, D, 50 > | |
< T0, B, 0, 50 > | < T0, B, 0 > | |
현재 | < T0, B, 0 > < T2, D, 50 > < T2, abort> |