복구 알고리즘
- 트랜잭션 롤백
트랜잭션 롤백은 시스템 failure 후 복구 과정이 아닌 정상적인 상황에서 발생한다.
트랜잭션 $T_{i}$의 롤백은 다음과 같이 수행된다.
1. 로그를 역방향으로 스캔한다.
$T_{i}$의 로그 레코드 <$T_{i}, X_{j}, V_{1}, V_{2}$>를 만나면,
데이터 항목 $X_{j}$에 값 $V_{1}$을 기록하고,
undo 작업에 대한 로그 레코드 <$T_{i}, X_{j}, V_{1}$>를 기록한다.
이때, 이런 로그 레코드를 보상 로그 레코드(compensation log record)라고 부른다.
2. <$T_{i} start$>를 만나면 역방향 탐색을 중단한다.
그리고 <$T_{i} abort$> 로그 레코드를 로그에 기록한다.
- 시스템 failure 후의 복구
두 가지 단계를 거쳐 복구가 이루어진다.
redo 단계: 마지막 검사점부터 순방향으로 로그를 탐색하며 모든 트랜잭션의 갱신 작업을 redo 한다.
1. 마지막 <checkpoint L> 레코드를 찾고, undo-list를 L로 초기화한다.
2. <checkpoint L> 레코드 이후부터 순방향으로 탐색한다.
<$T_{i}, X_{j}, V_{1}, V_{2}$> 레코드를 만나면, 데이터 항목 $X_{j}$에 값 $V_{2}$를 기록하는 redo 작업을 수행한다.
<$T_{i} start$> 레코드를 만나면, $T_{i}$를 undo-list에 추가한다.
<$T_{i} abort$>나 <$T_{i} commit$> 레코드를 만나면, $T_{i}$를 undo-list에서 제거한다.
redo 단계가 끝나면 undo-list는 미완료 트랜잭션, 즉 failure 이전에 commit하지 못했거나 rollback을 완료하지 못한 트랜잭션을 포함하게 된다.
undo 단계: 로그를 마지막부터 역방향으로 탐색해 undo-list에 있는 모든 트랜잭션을 롤백한다.
1. undo-list에 속한 트랜잭션의 <$T_{i}, X_{j}, V_{1}, V_{2}$> 레코드를 만나면, 트랜잭션 롤백과 같은 방식으로 undo를 실행한다.
데이터 항목 $X_{j}$에 값 $V_{1}$을 기록하고,
undo 작업에 대한 로그 레코드 <$T_{i}, X_{j}, V_{1}$>를 기록한다.
2. undo-list에 속한 트랜잭션의 <$T_{i} start$> 레코드를 만나면, <$T_{i} abort$>를 기록하고 $T_{i}$를 undo-list에서 제거한다.
3. undo-list가 비어 있는 상태가 되면, undo 단계를 종료한다.
undo 단계가 끝나면 일상적인 트랜잭션 처리를 다시 시작할 수 있다.
버퍼 관리
- 로그 레코드 버퍼링
로그 레코드 버퍼링(log record buffering)은 로그 레코드가 바로 안정 저장 장치로 출력되는 대신에, 메인 메모리의 로그 버퍼에 임시로 저장되는 것을 의미한다.
로그 레코드는 다음과 같은 상황에서 안정 저장 장치로 출력된다.
1. 로그 버퍼 내의 한 블록이 로그 레코드로 가득 찰 때 안정 저장 장치로 출력된다.
2. log force 연산이 수행될 때 안정 저장 장치로 출력된다.
log force 연산은 한 트랜잭션이 commit 하기 위해서 수행되거나, checkpoint managet나 DB buffer manager로부터 요구받았을 때 수행된다.
로그 레코드 버퍼링을 위해서 다음과 같은 규칙들이 지켜져야 한다.
1. 로그 레코드는 만들어진 순서대로 안정 저장 장치로 출력되어야 한다.
2. 트랜잭션 $T_{i}$는 <$T_{i} commit$> 레코드가 안정 저장 장치에 출력된 후에 commit 상태가 된다.
3. 메인 메모리의 데이터 블록이 데이터베이스에 출력되기 전에, 데이터 블록에 포함된 데이터 항목과 관련된 모든 로그 레코드를 안정 저장 장치에 출력해야 한다.
이 규칙을 write-ahead logging(WAL)이라고 한다.
- 데이터베이스 버퍼링
시스템은 데이터베이스를 디스크에 저장하고, 필요할 때 메인 메모리로 데이터 블록을 가져온다.
새 블록이 필요할 때 버퍼가 가득 차있으면, 기존 블록을 버퍼에서 제거해야 한다.
제거하도록 선택된 블록이 갱신된 경우에, 해당 블록을 디스크로 출력해야 한다.
복구 알고리즘은 no-force policy와 steal policy를 지원한다.
no-force policy는 트랜잭션이 수정한 블록을 모두 디스크에 출력하지 않아도 트랜잭션이 commit 하는 것을 허용한다.
steal policy는 트랜잭션이 commit 하지 않아도 수정한 블록을 디스크에 출력하는 것을 허용한다.
한 블록을 디스크에 출력하는 동안에는 그 블록에 대해서 어떠한 갱신 작업을 수행할 수 없도록 해야 한다. (WAL 규칙에 의해)
이는 exclusive lock(latch)를 이용해 막을 수 있다.
블록을 디스크에 출력할 때 다음과 같은 순서를 따른다.
1. 블록에 대해서 exclusive latch를 획득해 어떤 트랜잭션도 해당 블록에 쓰기 작업을 알 수 없도록 보장한다.
2. 로그 버퍼의 로그 레코드를 안정 저장 장치에 출력하는 log flush를 수행한다.
3. 블록을 디스크에 출력한다.
4. 블록에 대한 latch를 해제한다.
비휘발성 저장 장치에 손실이 발생하는 장애
비휘발성 저장 장치의 정보가 손실되는 장애를 대비하기 위해서, 주기적으로 데이터베이스의 모든 내용을 안정 저장 장치로 dump 한다.
dump 작업 중에 어떤 트랜잭션도 작동하지 않을 것을 요구하며, 다음과 같은 단계로 진행된다.
1. 현재 메인 메모리에 존재하는 모든 로그 레코드를 안정 저장 장치에 출력한다.
2. 모든 버퍼 블록을 디스크에 출력한다.
3. 데이터베이스의 내용을 안정 저장 장치에 복사한다.
4. 로그 레코드 <dump>를 안정 저장 장치에 출력한다.
'전공 > 데이터베이스' 카테고리의 다른 글
동시성 제어 - (2) (0) | 2021.12.12 |
---|---|
동시성 제어 - (1) (0) | 2021.12.12 |
복구 시스템 - (2) (0) | 2021.12.11 |
복구 시스템 - (1) (0) | 2021.12.06 |
트랜잭션 - (2) (0) | 2021.12.06 |