데이터보다 먼저 기록하는 복구의 약속: WAL
WAL은 Write-Ahead Logging의 약자로, 변경된 데이터 페이지를 영속 저장장치에 쓰기 전에 그 변경을 복구하는 데 필요한 로그를 먼저 영속화하는 규칙이다. 데이터베이스는 성능을 위해 페이지를 메모리에 모아 두고 나중에 쓸 수 있으므로, 크래시가 일어나도 커밋한 변경을 다시 만들 근거가 필요하다.
WAL의 핵심은 필요한 로그가 데이터 페이지보다 먼저 안전하게 저장되는 순서다.
데이터 페이지와 로그의 순서
계좌 잔액을 100에서 70으로 바꾸면 메모리의 데이터 페이지가 수정된다. 그 페이지를 디스크에 쓰기 전에 해당 수정의 로그가 안전하게 저장되어야 한다. 그렇지 않으면 디스크에는 새 데이터 일부가 있는데 그 변경의 출처와 복구 정보는 없는 상태가 생길 수 있다. WAL의 선행 규칙은 이런 순서 문제를 다룬다.
성공적인 커밋의 지속성을 제공하려면 관련 로그와 커밋에 필요한 정보가 정해진 내구성 조건을 만족해야 한다. 데이터 페이지 전체가 즉시 저장되지 않아도 로그를 이용해 이후 복구할 수 있다. 물론 실제 커밋 응답 시점과 동기화 정책은 DB 설정과 저장장치의 동작에 따라 확인해야 한다.
LSN은 로그 위치를 식별하는 순서 정보다. 데이터 페이지에 반영된 로그 위치와 복구 중 처리하는 위치를 비교하면 어떤 변경이 이미 반영되었는지 판단하는 데 도움을 준다. 로그 레코드의 형태는 시스템마다 다르며 논리적인 작업, 물리적인 페이지 변화 또는 그 조합을 기록할 수 있다.
크래시 뒤에 다시 하는 일
디스크 페이지에 커밋한 수정이 아직 반영되지 않은 경우 복구는 필요한 로그를 읽고 변경을 재실행할 수 있다. 이를 redo라고 부른다. 취소해야 할 변경을 되돌리는 undo의 필요성과 방식은 시스템의 저장 및 트랜잭션 설계에 따라 다르다. 모든 WAL 구현이 동일한 redo/undo 절차를 수행한다고 말하면 부정확하다.
로그를 무조건 전체 재생해서 같은 변경을 두 번 적용하면 안 되는 경우가 있다. 그래서 복구는 페이지의 상태와 로그 위치, 레코드의 규칙을 이용해 올바르게 재적용한다. 잔액을 30 더 빼라는 업무 요청과, 페이지에 특정 변경이 반영되어야 한다는 복구 기록은 같은 의미로 처리할 수 없다.
순차 로그 쓰기는 여러 데이터 페이지를 흩어서 즉시 저장하는 것보다 효율적일 수 있다. 여러 커밋의 로그 동기화를 모으는 그룹 커밋도 비용을 줄이는 방법이다. 하지만 장치를 실제로 동기화하는 지연과 로그 양은 남으며, 로그를 많이 생성하는 작업은 쓰기 처리량과 복제 전송에 영향을 줄 수 있다.
로그를 남긴다고 모든 장애가 사라지지는 않는다
로그도 저장장치에 있고 올바른 동기화가 필요하다. 운영체제 캐시에 쓰였다는 사실과 전원 장애 뒤에도 안전하다는 사실은 같지 않을 수 있다. 성능 옵션으로 동기화를 생략하면 장애 시 커밋한 변경의 손실 범위가 달라질 수 있다. 장치가 보고한 완료와 실제 보존 조건을 이해해야 한다.
WAL은 백업과도 다르다. 로그가 같은 손상된 저장장치에만 있으면 저장장치 전체의 상실을 해결하지 못할 수 있다. 백업과 보관된 로그를 적절히 결합하면 시점 복구 같은 기능을 제공할 수 있지만, 기준 백업과 필요한 로그 구간이 함께 준비되어야 한다.
체크포인트는 복구에 필요한 로그 탐색 범위를 관리하는 데 도움을 준다. 로그를 언제 지울 수 있는지는 데이터 반영뿐 아니라 복제와 보관, 복구 요구에도 달려 있다. WAL을 공부할 때는 수정, 로그 영속화, 데이터 페이지 쓰기와 커밋 응답의 순서를 그려 보는 것이 좋다. 저장 순서라는 작은 규칙이 실패 후에도 결과를 설명할 수 있는 근거를 만든다.