이 노트는 ‘커밋 응답을 받았는가’, ‘로그가 장치에 내구화됐는가’, ‘데이터 페이지가 최종 위치에 쓰였는가’를 서로 다른 사건으로 놓고 복구 경계를 계산합니다. WAL 선행 순서와 group commit의 비용 분담을 기본 모델로 삼은 뒤, 기준 백업과 연속 로그로 시점 복구를 구성하고, 복원 환경에서 outbox와 외부 결제를 재실행하지 않도록 격리하는 판단까지 연결합니다.
WAL 선행 기록과 메모리 내 커밋 데이터 페이지 복구
DB가 모든 변경 페이지를 매 커밋마다 최종 위치에 쓰면 많은 랜덤 I/O가 필요할 수 있습니다. WAL은 변경을 복구할 로그를 먼저 내구 기록하고 데이터 페이지는 나중에 반영할 수 있게 합니다. 변경 페이지가 저장되기 전에 그 페이지 복구에 필요한 로그가 먼저 안전한 지점에 있어야 하는 write-ahead 순서를 지킵니다.
커밋 성공의 정확한 내구 지점은 DB 설정과 OS·파일시스템·장치의 flush 계약에 달렸습니다. 로그가 DB 메모리나 OS cache에만 있는데 성공을 반환하는 비동기 정책은 전원 손실에서 최근 쓰기를 잃을 수 있습니다. write 시스템 호출 성공과 장치 내구화를 같은 것으로 보지 않습니다.
로그·페이지·응답의 기록·내구 사건 구분
| 사건 | 의미 | 남는 조건 |
|---|---|---|
| 로그 레코드 생성 | 복구 정보가 준비됨 | 메모리만일 수 있음 |
| 약속한 WAL flush | 로그 내구 조건 충족 | 장치·설정 보장 |
| commit 응답 | 해당 정책상 성공 통지 | 클라이언트 도달 여부 |
| 데이터 페이지 기록 | 최종 페이지 반영 | 모든 커밋과 같은 시각 아님 |
| replica 확인 | 특정 복제 단계 확인 | 수신·flush·replay·승격 범위 |
PostgreSQL WAL, InnoDB의 redo/binlog, SQL Server transaction log는 설정·복구·동기화 범위가 서로 다르므로 같은 순서로 설명할 수 없습니다. redo는 기록된 변경을 장애 뒤 다시 적용하는 단계이고, undo는 완료되지 않은 변경의 효과를 되돌리는 단계이며, MVCC 가시성은 각 트랜잭션이 어떤 행 버전을 읽을지 정하는 규칙입니다.
따라서 미완료 변경이 정상 커밋처럼 보이지 않도록 실제 엔진의 redo·undo·MVCC 복구 절차를 따로 따라야 하며, 모든 엔진이 WAL에서 같은 방식으로 undo한다고 가정하면 안 됩니다.
그림을 글로 읽기
- 변경·커밋 로그 준비
- 정책상 내구 로그 기록
- 커밋 성공 응답
- 더티 페이지 후속 기록
- 변경·커밋 로그 준비 → 정책상 내구 로그 기록: write-ahead
- 정책상 내구 로그 기록 → 커밋 성공 응답: 내구 정책 충족
- 정책상 내구 로그 기록 → 더티 페이지 후속 기록: 페이지보다 먼저
Group Commit과 거래별 Flush 비용 분담
여러 커밋의 로그를 한 flush에 포함하면 디스크 왕복 비용을 분담할 수 있습니다. 각 거래는 자신의 로그가 약속한 지점까지 포함된 뒤 응답해야 같은 내구 계약을 유지합니다. 묶이기를 기다리는 시간과 부하가 낮을 때의 지연·throughput을 함께 봅니다. group commit 자체가 데이터를 일부 잃는 기능인 것은 아니며 flush 지연 정책과 구분합니다.
checkpoint는 메모리에서 바뀌었지만 최종 페이지로 아직 기록되지 않은 더티 페이지의 상태와 재시작 때 로그를 재생할 시작 범위를 다루는 지점입니다. 너무 자주 만들면 정상 I/O와 추가 로그 비용이 늘 수 있고, 너무 드물게 만들면 재시작 복구량과 로그 공간이 커질 수 있습니다. checkpoint는 모든 커밋을 한꺼번에 만드는 거래도, 백업도 아니므로, 백업·replica·CDC 보존 때문에 checkpoint 이전 로그가 더 오래 필요할 수 있다는 점을 별도로 계산해야 합니다.
시점 복구의 기준 백업과 연속 로그
오전 1시 백업 뒤 10시 5분의 잘못된 DELETE 직전으로 돌아가려면 해당 기준 백업과 이후 목표 지점까지의 연속 로그·필요 키·설정이 있어야 합니다. 중간 로그 하나가 없으면 그 뒤로 재생할 수 없을 수 있습니다. DB별 recovery model·archive·binlog·log backup 절차를 확인합니다.
벽시계 시각만으로 목표를 모호하게 정하지 말고 문제 transaction·로그 위치·엔진의 inclusive/exclusive target 의미를 확인합니다. 먼저 외부 효과가 차단된 별도 환경에 복원해 데이터를 검사합니다. 운영 DB를 급히 덮으면 삭제 이후 정상 변경도 잃을 수 있습니다.
복원 Outbox와 외부 결제 재실행 차단
복원 DB에는 과거 미발행 outbox·미완료 작업·이미 외부에서 성공한 결제가 남을 수 있습니다. 복원 환경의 네트워크·자격·worker 실행을 제한하고 외부 원장과 대사합니다. 데이터 복원 성공을 이유로 예전 작업을 무조건 재실행하지 않습니다.
일부 삭제 행만 운영에 가져올 때는 현재 version·키·외래키·후속 변경·개인정보 상태와 충돌을 확인합니다. 같은 이름의 신규 계정에 옛 자료를 잘못 연결하지 않습니다. 기준 복원과 선택적 병합은 다른 승인·검증 범위입니다.
성공 응답 쓰기와 불확실한 쓰기의 결과 확인
정해진 내구 정책에서 성공 응답을 받은 커밋은 해당 장애 모형의 복구 뒤 존재해야 합니다. 응답을 못 받은 요청은 커밋되었거나 아닐 수 있으므로 논리 ID로 결과를 조회해 한 번의 효과로 수렴시켜야 합니다. 비동기 replica 승격에서 dedupe 기록까지 손실될 수 있는 한계는 별도입니다.
정상 종료만으로는 내구성을 확인할 수 없으므로, 승인된 격리 환경에서 프로세스 중단·호스트 손실·로그 연속성 누락을 재현하고 실제 restore까지 수행해야 합니다. 가장 최근에 유효하게 복구할 수 있는 위치와 장애 시점을 비교해 RPO(얼마나 최근 데이터까지 보존되는지)를 계산하고, 서비스가 쓰기를 다시 받기까지 걸린 시간으로 RTO(복구 시간)를 측정합니다. 다만 현재 작업에서는 DB 전원 손실·flush·PITR 실험을 실행하지 않았으므로, 이 본문은 특정 엔진의 실험 결과가 아니라 내구와 복구 계약의 설명으로 읽어야 합니다.
재현 연습은 실제 운영 데이터가 아닌 격리된 합성 DB에서 로그 생성, 약속된 flush, commit 응답, 데이터 페이지 기록을 시간순으로 표시하는 것입니다. 예상 결과는 commit 응답 전에 필요한 WAL 내구 사건이 없으면 해당 성공을 내구 커밋으로 분류할 수 없고, 응답을 잃은 요청은 논리 ID 조회로 커밋 여부를 확인해야 한다는 것입니다. 이어 기준 백업 뒤 로그 한 조각을 의도적으로 제외하면 목표 시점까지 복구할 수 없거나 복구 위치가 앞당겨져 RPO가 커지는지 확인합니다.