[DB] 회복

2023. 12. 21. 03:01CS/DataBase

회복은 데이터베이스에 장애가 발생했을 때 데이터베이스를 일관성 있는 상태로 되돌리는 dbms의 기능이다. 데이터베이스 시스템에서 발생할 수 있는 장애의 유형은 다음과 같다.

  1. 시스템 충돌 : 하드웨어 혹은 소프트웨어의 오류로 주기억장치가 손실되는 것을 말한다. 처리 중인 프로그램과 데이터의 일부 혹은 전부가 손실된다.
  2. 미디어 장애 : 헤드 충돌이나 읽기 장애로 보조기억장치가 손실되는 것을 말한다. 보조기억장치에 저장 중인 데이터의 일부 혹은 전부가 손실된다.
  3. 응용 소프트웨어 오류 : 데이터베이스에 접근하는 소프트웨어의 논리적인 오류로 트랜잭션의 수행이 실패하는 것을 말한다.
  4. 자연재해 : 화재, 홍수, 지진, 정전 등에 의해 컴퓨터 시스템이 손상되는 것을 말한다.
  5. 부주의 혹은 태업 : 운영자나 사용자의 부주의로 데이터가 손실되거나 의도적인 손상을 입는 것을 말한다.

이중 회복에 중점을 두는 유형은 시스템 충돌, 미디어 장애, 응용 소프트웨어 오류이다. 이러한 장애는 장애의 내용이 무엇이든 상관없이 두 가지 결과를 도출한다. 하나는 변경 중인 데이터를 갖고 있는 주기억장치가 손실되는 것이고, 또 하나는 데이터베이스가 저장된 하드 디스크가 손실되는 것이다.

 

트랜잭션과 회복

 

트랜잭션은 데이터베이스 회복의 단위이다. 트랜잭션은 데이터의 변경 내용을 한순간에 모두 데이터베이스에 기록하지 않는다. 일단 변경한 내용(버퍼)을 로그(임시 디스크)에 기록한 후 데이터베이스에 반영한다. dbms의 회복 관리자는 트랜잭션의 ACID 성질 중 원자성과 지속성을 보장하여 장애로부터 데이터베이스를 보호한다.

장애가 발생하면 로그의 내용을 참조하여 트랜잭션의 변경 내용을 모두 반영하거나 아니면 아예 반영하지 않는 방법으로 원자성을 보장한다. 지속성도 마찬가지다. 트랜잭션이 일단 COMMIT 한 내용은 로그를 이용하여 반드시 데이터베이스에 기록한다.

 

트랜잭션은 시작-수행-부분완료-완료의 과정을 거쳐 진행된다. COMMIT은 트랜잭션의 부분완료시키는 명령어로 트랜잭션의 종료를 사용자나 다른 트랜잭션에게 알린다. 이 단계를 거치면 트랜잭션이 변경한 내용이 버퍼뿐만 아니라 재해에 대비하여 로그(임시 디스크)에도 저장된다. 이후 DBMS가 다른 작업의 상황을 보면서 버퍼의 내용을 하드디스크에 기록하고 기록이 끝나면 최종적으로 완료한다. COMMIT 완료 후에는 다른 트랜잭션이 해당 데이터를 자유롭게 사용할 수 있다.

  1. 트랜잭션이 시작하면 수행 상태가 된다.
  2. 정상적으로 수행(B-1)이 되면 COMMIT 문을 만나 부분완료된다.
  3. 부분완료 후 버퍼의 내용을 데이터베이스에 기록하면(B-2) 트랜잭션이 최종완료된다,
  4. 만약 수행중 문제가 생겨(C-1) 완료 전에 실패하면 취소과정을 거쳐(C-2) 이제까지 진행한 작업을 거꾸로 돌려놓는다. 이미 변경된 데이터는 로그를 이용해 다시 되돌린다.
  5. 부분완료를 했으나 실패가 일어난 경우라면(D), 취소 과정을 거쳐(C-2) 이제까지 진행한 작업을 거꾸로 돌려놓는다. 부분완료 후 실패하는 경우는 컴퓨터시스템 장애, 트랜잭션 오류, 데드락 등 여러 원인이 있을 수 있다.

 

 

로그 파일

 

DBMS는 트랜잭션이 수행 중이거나 수행이 종료된 후 발생하는 데이터베이스 손실을 방지하기 위해 트랜잭션의 데이터베이스 기록을 추적하는 로그 파일을 사용한다. 로그 파일은 트랜잭션이 반영한 모든 데이터의 변경사항을 데이터베이스에 기록하기 전에 미리 기록해두는 별도의 데이터베이스이다. 안전하게 하드디스크에 저장되며 전원과 관계없이 기록이 남아있다.

로그 파일에 저장된 로그의 구조는 다음과 같다 <트랜잭션번호, 로그 타입, 데이터 항목 이름, 수정 전 값, 수정 후 값>

여기서 로그 타입은 트랜잭션의 연산 타입 START, INSERT, UPDATE, DELETE, ABOUT, COMMIT 등이 있다. 수정 전 값은 데이터의 변경 전 값을 나타내고 수정 후 값은 연산의 결과로 변경된 값을 나타낸다.

 

<T1, START>
<T1, UPDATE, Customer(박지성).balance, 100000, 900000>
<T1, UPDATE, Customer(김연아).balance, 100000, 1900000>
<T1, COMMIT>

 

로그 파일을 이용한 회복

 

데이터를 변경 기록을 저장해 둔 로그 파일을 이용하면 시스템 장애도 복구할 수 있다. 다음의 예를 통해 살펴보자.

 

두개의 트랜잭션이 실행된다고 가정하자. 편의상 트랜잭션의 연산 SELECT, UPDATE는 read_item(), write_item()으로 대체한다. 트랜잭션은 각각 데이터 A, B, C, D를 읽거나 쓰는 작업을 수행한다. 데이터 (A, B, C, D)의 초기값은 (100, 200, 300, 400)이다.

 

트랜잭션이 T1 → T2 순으로 실행된다면 하단 그림과 같은 로그 파일이 생성된다. 트랜잭션 T1의 경우 START, UPDATE, COMMIT 연산으로 구성된다. read_item()은 데이터를 읽는 연산이기 때문에 데이터 값을 변경시키지 않아 로그에 기록되지 않는다. write_item()은 데이터 값을 변경 시키기 때문에 로그에 기록된다.

 

 

로그를 이용한 회복 방법은 다음과 같다.

시스템 운영 중 장애가 발생하여 시스템이 다시 가동되었을 때 DBMS는 로그 파일을 먼저 사펴본다. DBMS는 트랜잭션이 종료되었는지 혹은 중단되었는지 여부를 판단하여 종료된 트랜잭션은 종료를 확정하기 위하여 재실행(REDO)을 진행하고, 중단된 트랜잭션은 없던일로 돌리기 위해 취소(UNDO)를 진행한다. 이 두 작업은 트랜잭션이 로그 데이터베이스에 기록한 모든 값에 대하여(변경 전, 후 값) 중 어느 하나를 데이터베이스에 맞는 값으로 수정하는 작업이다.

 

트랜잭션의 재실행

장애가 발생한 후 시스템을 다시 가동을 했을 때, 로그 파일에 트랜잭션의 시작과 종료가 있는 경우이다. COMMIT 연산이 로그에 있다는 것은 트랜잭션이 모두 완료되었다는 의미이다. 다만, 변경 내용이 버퍼에서 데이터베이스에 기록되지 않았을 가능성이 있다. 로그를 보면서 트랜잭션이 변경한 내용을 데이터베이스에 다시 기록하는 과정이 필요하다. 이 과정을 REDO라고 한다.

 

트랜잭션의 취소

장애가 발생한 후 시스템을 다시 가동했을 때, 로그 파일에 트랜잭션의 시작만 있고 종료가 없는 경우이다. COMMIT 연산이 로그에 보이지 않는다는 것은 트랜잭션이 완료되지 못했다는 의미로, 트랜잭션이 한 일을 모두 취소해야 한다. 이 경우 완료하지 못 했지만 버퍼의 변경 내용이 데이터베이스에 기록되어 있을 가능성이 있기 때문에 로그를 보면서 트랜잭션이 변경한 내용을 데이터베이스에서 원상복구시켜야 한다. 이 과정을 UNDO 라고 한다.

 

트랜잭션이 반드시 부분완료된 후 변경 내용을 데이터베이스에 기록하는 방법

 

즉시갱신

장점 :즉시갱신은 버퍼 → 로그파일, 버퍼 → 데이터베이스 작업이 부분완료 전에 동시에 진행될 수 있으며, 부분완료 전에 버퍼의 갱신 데이터는 로그에 기록이 진행이 된 상태이며 부분완료 전에 버퍼의 일부 내용이 실제 데이터베이스에 반영이 될 수 있다. 

 

단점 : 즉시갱신은 시스템 운영 시 데이터베이스에 입출력 연산이 증가하는 단점이 있다

 

지연갱신

장점 : 지연갱신은 버퍼 → 로그 파일이 모두 끝난 후 부분완료를 하고 이후 버퍼 → 데이터베이스 작업을 진행하는 방법이다. 부분완료 전에는 갱신 내용이 실제 데이터베이스에 반영이 되지 않는 상태이다.

지연갱신은 즉시 갱신과 마찬가지로 부분완료가 되면 최소한 버퍼의 갱신 데이터는 로그에 모두 기록이 끝난 상태지만, 데이터베이스에 반영은 되지 않은 상태이다. 지연갱신 방법을 사용하면 데이터베이스에 반영하는 작업은 지연되지만, 장애가 발생할 경우 로그에 START 만 나타나느 트랜잭션은 취소 작업을 할 필요가 없는 장점이 있다.

 

단점 : 지연갱신은 시스템 복구 시 복구시간이 좀더 걸리는 단점이 있다.

 

체크포인트를 이용한 회복

 

로그를 이용한 회복은 시스템에 장애가 일어났을 때 어느 시점까지 되돌아가야 하는지 알 수 없다. 트랜잭션이 많은 응용의 경우 하루 이상 되돌아가서 복구하는 것은 사실상 불가능하다. 회복 시 많은 양의 로그를 검색하고 갱신하는 시간을 줄이기 위하여 몇 십 분 단위로 데이터베이스와 트랜잭션 로그 파일을 동기화한 후 동기화한 시점을 로그 파일에 기록해두는 방법 혹은 그 시점을 체크포인트라고 한다.

  • 주기억장치의 로그 레코드를 모두 하드디스크의 로그 파일에 저장한다.
  • 버퍼에 있는 변경된 내용을 하드디스크의 데이터베이스에 저장한다(즉시갱신 경우).
  • 체크포인트를 로그 파일에 표시한다.

체크포인트가 있으면 로그를 이용한 회복 기법은 좀 더 간단하다. 트랜잭션의 로그 기록에 따라 회복하는 방법은 다음과 같다.

 

  • 체크포인트 이전에 COMMIT 기록이 있는 트랜잭션의 경우
    • 아무 작업이 필요 없다. 로그에 체크포인트가 나타나느 시점은 이미 변경 내용이 체크포인트에 의하여 데이터베이스에 모두 기록된 후이기 때문이다(즉시갱신, 지연갱신).
  • 체크포인트 이후에 COMMIT 기록이 있는 트랜잭션의 경우
    • REDO를 진행한다. 체크포인트 이후에 변경 내용이 데이터베이스에 반영되지 않을 가능성이 있으므로 REDO를 진행한다(즉시갱신, 지연갱신).
  • 체크포인트 이후에 COMMIT 기록이 없는 트랜잭션의 경우
    • 즉시갱신 방법을 사용했다면 UNDO를 진행한다. 버퍼의 내용이 반영됐을 수도 있기 때문에 원상복구시켜야 한다. 반면 지연갱신 방법을 사용했다면 아무것도 할 필요가 없다. 지연갱신 방법은 COMMIT 이전에는 버퍼의 내용을 데이터베이스에 반영하지 않았기 때문이다.
  •  

'CS > DataBase' 카테고리의 다른 글

[DB] JOIN 정리  (0) 2023.12.30
[DB] 트랜잭션 고립 수준  (0) 2023.12.21
[DB] 동시성 제어  (0) 2023.12.20
[DB] 트랜잭션  (0) 2023.12.20
[DB] 정규화  (0) 2023.12.19