1. snapshot은 최근 2개로 운영 ( retain_last = 2 )
예시
CALL system.expire_snapshots(
table => 'mydb.mytable',
older_than => TIMESTAMP '2025-09-01 00:00:00',
retain_last => 2
);
- 최신 스냅샷이 #105일 때 위와 같이
retain_last = 2 를 설정
- 보존: #105(최신), #104(직전)
- 삭제 가능: #103 이하(조건 충족 시)
이유 (운영 3대 안전망)
- 롤백 안전망: 최신 스냅샷에 문제가 생겨도 직전으로 즉시 복원
- 읽기 안정성: 누군가 직전 스냅샷 기준으로 읽는 중일 수 있음
- 안전한 GC: Iceberg는 “어느 스냅샷에서도 참조되지 않는 파일만” 물리 삭제 → 직전 스냅샷을 남겨둬야 방금 전 파일이 orphan 오판으로 날아가지 않음
즉, 최소 2개 보존은 롤백·동시성·GC 측면의 최소 안전선
2. 스냅샷에 담긴 것과 역할
스냅샷이 담는 정보
- Snapshot ID
- Timestamp
- Operation type(append/overwrite/delete)
- Manifest List Path
- Parent Snapshot ID
- 스냅샷은 파일을 직접 담지 않고, Snapshot → Manifest List → Manifest → Data/Delete Files 계층으로 “해당 시점의 파일 집합”을 간접 참조
스냅샷의 기능
- 시간여행: 과거 스냅샷 기준 조회
- 증분 읽기: 이전 스냅샷 이후 변경분만 읽기
- 롤백: 특정 스냅샷으로 즉시 복원
- GC 기준 제공: 참조가 끊긴 파일만 물리 삭제
Catalog(Hive/Glue/Nessie)
↓
Table Metadata (metadata.json)
↓
Snapshot
↓
Manifest List
↓
Manifest
↓
Data Files / Delete Files (Parquet/ORC…)
3. Upsert(증분) 시 실제 동작
- Iceberg는 기존 파일을 “수정”하지 않으면, Delete 파일과 새 Data 파일을 추가하고 새 스냅샷을 만든다.
예시
- 스냅샷
#105: Data Files = A, B (행: 1,2,3)
- Upsert:
row=2 업데이트 + row=4 추가
- Delete D:
row=2 삭제
- Data C:
row=2’, row=4 기록
- 스냅샷
#106: A, B, C + Delete D 참조
- 쿼리는
D를 적용해 2를 빼고 2’, 4를 본다.
#105는 불변이며 A, B만 계속 가리킨다.
4. Iceberg 운영 중 발생한 에러 정리
ValidationException: Cannot commit, missing data files
- Snapshot 단계에서 발생하는 에러로 수정/삭제하려고 계획했던 파일(A,B,C)이 커밋 시 최신 스냅샷에서 더 이상 참조되지 않았을때 발생
- 예시
DELETE 발생: 최신 snapshot #105는 A,B,C 참조
- 그 사이 DataFile Compaction으로
A,B,C → D 교체, 새 스냅샷 #106 커밋
- 커밋 시 최신은
D만 참조 → 계획 전제 붕괴 → ValidationException
- S3엔 파일이 있어도 “최신 스냅샷 참조 관계”가 달라져 메타데이터 레벨 충돌로 커밋이 막힘
- Iceberg는 Optimistic Concurrency로 Writer(쓰기 작업자)는 “내가 업데이트하려는 시점의 스냅샷이 여전히 최신일 것이다”라고 낙관적으로 가정하고 새 메타데이터 파일을 생성
Writers create table metadata files optimistically, assuming that
the current version will not be changed before the writer's commit.
Once a writer has created an update, it commits by swapping
the table’s metadata file pointer from the base version to the new version
- 내가 작업 시작 시 참조한 스냅샷 = 여전히 최신 → 커밋 성공
- 내가 작업 시작 시 참조한 스냅샷 < 이미 새로운 스냅샷이 생김 → 충돌 (ValidationException)
NotFoundException: File does not exist Avro
- 실제 파일 읽기 단계에서 발생하는 에러로 Snapshot 에서는 파일이 존재한다고 가정하고 가리키는데 실제 S3/HDFS에 물리적으로 없음(파일이 없음)
- expire_snapshots를 하고 rewrite_manifests를 통해 메타데이터 최적화를 진행할때 특정 스냅샷 파일이 사라졌을 때도 해당 에러 발생 (따라서 이것 때문에 retain_last = 2로 스냅샷 운영)
5. Equality Delete, Position Delete
- Equality Delete
- 자신보다 작은 Data Sequence Number의 Data File에 적용
- 동일한 커밋에서 새롭게 들어온 레코드는 삭제하지 않음
- 하지만 만약 동일한 커밋에서 시퀀스/순서/리더 해석이 꼬이면 중복·증발 위험이 존재
- Position Delete
- 자신을 포함하여 작거나 같은 Data Sequence Number의 Data File에 적용
- 동일 커밋 내에서도 이전 행만 확실히 제거 가능