DB

Log-Based Recovery

아뵹젼 2022. 4. 21.

Log Block Buffering

log recored는 우선 메인 메모리의 buffer에 저장을 하며, 적절한 시점이 되면 storage에 있는 log db에 저장하게 된다.

버퍼에 있는 로그 기록이 가득 찼거나, log force 연산이 실행될 때 stable storage 로 이동한다.

Log Force 는 commit 을 할 때 stable storage에 쓴다.

 

Group commit : log 버퍼를 블락만큼 채워서 한 번의 output 연산으로 디스크에 쓰면 I/O 비용을 줄일 수 있을 것이다.

 

 

 

Logging rule

  • 로그 레코드는 반드시 생성된 순서대로 저장되어야한다. -> undo, redo 를 위함
  • 트랜잭션 Ti가 commit state가 되려면 <Ti, commit> 이 먼저 log db에 저장되어야 한다.
  • write-ahead logging (WAL) : 메인 메모리 내의 데이터 블록이 데이터베이스 (비휘발성 storage내에)에 output 될 수 있기 전에, 해당 블록의 데이터와 관련된 모든 로그 레코드가 stable storage에 output되어야 한다.                 
  • -> data block 을 디스크에 쓰기 전에, 로그를 먼저 저장해야 한다. (엄격하게 말하면 WAL 은 로그 내의 undo 정보가 stable storage로 output 될 것을 요구하는 것이다.)

 

A Recovery Algorithm

Logging(during normal operation)

<Ti start> : 트랜잭션이 시작될 때

<Ti, Xj, V1, V2> : 업데이트가 될 때

<Ti commit> : commit 될 때 

 

Transaction rollback (during normal operation)

Ti 는 roll back 해야 하는 트랜잭션이다.

정상적인 롤백 명령을 할 때 생성되는 로그이다.

rollback 시점으로 부터 backwards scan 을 하다가 <Ti, Xj, V1, V2> 를 만나게 된다.

이때 Xj 에 V1 을 쓰는 undo 작업을 진행한다.
그리고 <Ti, Xj, v1> 이라는 로그 기록을 작성한다.
-> 이러한 로그 기록을 compensation log record 라고 한다.

<Ti start>를 만나면 backwards scan 을 멈추고, <Ti abort> 로그 레코드를 남기게 된다.

 

 

two phase recovery algorithm

-> 이 알고리즘은 모든 트랜잭션에 대해서 update를 수행하기 때문에 redo-list 없이 undo-list만 만들어 낸다.

Redo phase : committed, aborted, incomplete 상태의 모든 트랜잭션에 대해 수행한다.

  • 마지막 <checkpoint L> 을 찾고, L 을 모두 undo-list 에 넣는다.
  • 이후 위의 <checkpoint L> 부터 로그를 Forward로 스캔한다.
  • 그러다가 <Ti, X, V1, V2> 를 만나면 X에 V2 를 write한다. (Redo)
  • 만약 <Ti start> 를 만난다면 Ti 를 undo-list 에 넣음
  • <Ti commit> 또는 <Ti abort> 를 만나면 Ti 를 undo-list 로부터 삭제한다.

Undo phase : incomplete 상태의 트랜잭션에 대해 수행한다.

  • 로그 끝에서부터 Backward 로 스캔한다.
  • 만약 <Ti, X, V1, V2> 를 만난다면 X에 V1 를 write(Undo) 한다. 그리고 <Ti, X, V1> 로그 를 남긴다.
  • 이는 undo-list 의 모든 트랜잭션 Ti 에 대해서 <Ti, start>를 만날때까지 계속한다. 그리고 <Ti, start> 를 만난다면 <Ti, abort> 로그 기록을 남기며, Ti 를 undo-list 로부터 제거한다.
  • undo-list 가 empty 할 때까지 계속한다.

위 과정의 undo phase에서 compensation log 가 필요한 이유는 무엇일까?

<Ti start> <Ti Xj V1 V2> 을 복구한다고 해보자.

원래는 <Ti Xj V1 V2> <Ti Xj V1> <Ti abort>와 같은 로그가 남을 것이다.

 

compensation log를 안 남기면 <Ti Xj V1 V2> <Ti abort> 이런 로그가 남을 것이다.

복구 도중 undo phase 진행 중에 failure가 또 발생했다고 하자. 그러면 다시 복구를 진행하게 된다.

redo phase에서는 Xj를 V2로 바꾸게 되고, <Ti abort>를 만나게 되면 undo-list에서 제거하기 때문에 undo phase 는 더 이상 진행되지 않을 것이다. 

그러나 Ti 는 checkpoint 이후에 시작되어씩 때문에 V1 으로 복구가 되어야 한다. 그러나 compensation log 를 남기지 않으면 Xj 가 V2 로 바뀌게 된다.

 

compensation log를 남긴다면? redo phase에서 Xj가 V2로 바뀌지만 <Ti Xj V1> 로그 레코드를 통해 다시 Xj 가 V1 으로 바뀌게 된다. 

 

 

 

redo phase

4. checkpoint에서 시작하고 undo-list={T0, T1}로 시작한다.

5. C을 600으로 write한다. 

6. T1을 undo-list에서 제거한다 -> undo-list={T0}

7. T2를 undo-list에 삽입한다. undo-list={T0,T2} 

8. A에 400을 write한다.

9. T0 가 어디선가 rollback 되었다는 것을 알 수 있다. 즉, crash 발생 전에 정상적인 롤백이 이루어졌음을 알 수 있다. 따라서 B를 old value 인 1900으로 write한다.

10. T0는 정상적으로 수행된 트랜잭션이므로 undo-list에서 뺀다. undo-list={T2}

11. C에 300을 write한다.

->undo-list={T2}

 

undo phase

11. T2가 undo-list에 있으므로 C를 600으로 write한다. -> 12 의 <T2, C, 600> 로그를 기록한다.

8. A를 500으로 write한다. -> 13의 <T2, A, 500> 로그를 기록한다.

7. T2 를 undo-list에서 뺀다. undo-list가 비어있으므로 undo phase를 완료한다. -> 14의 <T2, abort> 로그를 기록한다.

 

 

Fuzzy Checkpointing

checkpoint를 할 때 실행 중인 모든 트랜잭션을 중지하고 디스크에 버퍼의 값을 저장하게 된다.

이 때 트랜잭션을 중지하지 않고 checkpoint를 만드는 방법이 Fuzzy checkpointing이다.

  • 일시적으로 모든 트랜잭션의 update를 중단시킨다.
  • <checkpoint L> log 레코드를 기록하고, force log 를 수행한다. (로그 블럭을 stable stoarge 에 저장, WAL)
  • 업데이트된 buffer block 에 대해서 리스트 M을 만든다. -> dirty block 리스트
  • 일시적으로 멈춰두었던 트랜잭션들을 재개한다.
  • 리스트 M의 모든 블럭을 디스크에 저장한다. output 되는 동안 buffer block 이 업데이트 되면 안된다. -> latch 사용 / WAL 규칙을 만족해야 한다.
  • 가장 마지막에 수행한 checkpoint에 대한 포인터 last_checkpoint 를 방금 수행한 로그 레코드로 업데이트한다. 

이로서 checkpoint 이전의 모든 행위들은 디스크에 저장된 것이므로 이후의 과정에 대해서만 리커버리할 수 있음

 

recovery algorithm 이 fuzzy checkpoint 기법을 사용한다면 stable storage 에서 last_checkpoint 를 관리한다.

즉, recovery가 될 때 로그를 순회하면서 마지막 체크포인트를 탐색하는 것이 아니라, last_checkpoint 로 찾아가 바로 forward scanning 수행할 수 있게 된다.

 

Failure of Nonvolatile storage

non-volatile 저장장치 (disk) 의 손실을 방지하기 위해 dump를 사용한다.

데이터베이스의 전체 내용을 주기적으로 stable storage 에 dump 한다.

- 메인메모리에 있는 모든 로그 기록을 stable storage 로 output 한다.
- 모든 buffer block 을 디스크에 output 한다.
- 데이터베이스의 내용을 stable storage 에 copy한다.
- <dump> 로그를 stable storage 로 output 한다.

 

'DB' 카테고리의 다른 글

Logs  (0) 2022.04.21
Failure and Recovery  (0) 2022.04.21
Insert and Delete Operations  (0) 2022.04.20
Deadlock  (0) 2022.04.20
Multiple Granularity Locking  (0) 2022.04.20

댓글