Lakehouse Table Format — Understanding Apache Iceberg Through Its Metadata
Undo a region you deleted by mistake, and review the next day's data on a branch before publishing
한국어 원문으로 표시합니다.
목표
사흘 치 커밋 뒤에 한 지역을 통째로 지우는 사고를 내고, 타임트래블로 사고 전 상태를 읽고, 태그로 그 시점에 이름을 붙이고, 롤백으로 되돌린다. 이어서 다음 날 자료를 main 이 아닌 브랜치에 먼저 쓰고 검토한 뒤 main 을 앞당겨 발행한다.
왜 중요한가
Iceberg 의 모든 커밋은 옛 스냅샷을 지우지 않고 새 스냅샷을 더한다. 그래서 '어제 상태' 는 백업에서 꺼내는 것이 아니라 그 스냅샷의 파일 목록을 읽는 것이고, 되돌리기는 파일을 복사하는 것이 아니라 main 이라는 포인터를 옛 스냅샷으로 옮기는 것이다. 몇 초면 끝난다. 다만 옛 스냅샷은 영원하지 않다. 스냅샷 만료가 돌면 기준보다 오래된 것은 지워지고, ID 만 적어 둔 시점은 사라진다. 태그는 스냅샷에 이름을 붙이고 보존 기간을 따로 주어 만료로부터 지킨다. 브랜치는 반대 방향의 도구다. 새 자료를 main 이 아닌 곳에 먼저 커밋해 두고, 검사가 통과하면 main 을 그 스냅샷으로 앞당긴다. 읽는 사람은 검사 전의 자료를 한 번도 보지 않는다(write-audit-publish).
단계
- /root/ice/tt/days.py(앱
ice-tt-days)로lake.tt.orders(format-version 2)를 만들고 2026-03-01·02·03 을 하루에 한 커밋씩 넣으세요. - /root/ice/tt/accident.py(앱
ice-tt-accident)로DELETE FROM lake.tt.orders WHERE region = 'busan'을 돌리세요(일부러 내는 사고입니다). - /root/ice/tt/travel.py(앱
ice-tt-travel)로 세 번째 커밋(사고 직전) 스냅샷을 찾아 그때의 행 수·부산 행 수와 지금의 부산 행 수를 /root/ice/tt/out/travel.json 에 쓰세요. - /root/ice/tt/tag.py(앱
ice-tt-tag)로 그 스냅샷에 태그before_accident를RETAIN 7 DAYS로 붙이세요. - /root/ice/tt/rollback.py(앱
ice-tt-rollback)로rollback_to_snapshot을 불러 main 을 그 스냅샷으로 되돌리세요. - /root/ice/tt/branch.py(앱
ice-tt-branch)로 브랜치fix를 만들고 2026-03-04 를 그 브랜치에만 쓰세요. - /root/ice/tt/publish.py(앱
ice-tt-publish)로fast_forward를 불러 main 을fix로 앞당기세요. - /root/ice/tt/report.md 에
## 타임트래블## 롤백과 태그## 브랜치세 절을 쓰세요.
참고
- 스냅샷은
SELECT * FROM lake.tt.orders.snapshots, main 이 지나온 길은lake.tt.orders.history, 이름표는lake.tt.orders.refs로 봅니다. - 타임트래블:
SELECT … FROM 표 VERSION AS OF <스냅샷 ID 또는 태그·브랜치 이름>,TIMESTAMP AS OF '<시각>'. - 브랜치에 쓰기:
df.writeTo("lake.tt.orders.branch_fix").append()또는 SQL 의INSERT INTO lake.tt.orders.branch_fix …. - 흔한 실수: 롤백이 사고 스냅샷을 지운다고 믿는 것(지우지 않습니다 — 만료가 지웁니다), 태그를 걸기 전에 스냅샷 만료를 돌리는 것.
- 공식 문서: Branching and Tagging · Spark Queries — Time travel · Spark Procedures — rollback_to_snapshot · fast_forward · Spark DDL — Branching and Tagging DDL
사흘, 커밋 셋
/root/ice/tt/days.py 를 앱 이름 ice-tt-days 로 만들어 lake.tt.orders(열 여섯 개, 'format-version' = '2')를 만들고 2026-03-01·03-02·03-03 을 하루에 append() 한 번씩 넣으세요.
스냅샷 셋이 부모로 이어집니다. 채점기는 처음 세 스냅샷이 차례로 그날의 행 수를 더한 append 인지 봅니다. 여러 번 돌려 스냅샷이 늘었다면 DROP TABLE lake.tt.orders PURGE 뒤 다시 하세요.
사고 — 한 지역이 통째로 사라진다
/root/ice/tt/accident.py 를 앱 이름 ice-tt-accident 로 만들어 DELETE FROM lake.tt.orders WHERE region = 'busan' 을 돌리세요.
DELETE 도 커밋이라 네 번째 스냅샷이 생깁니다. 부산 행이 든 파일은 부산을 뺀 새 파일로 바뀌어 목록에 들어가고, 옛 파일은 목록에서만 빠질 뿐 디스크에는 그대로 있습니다. 채점기는 네 번째 스냅샷이 세 번째를 부모로 두고 부산 행이 없는지 봅니다.
타임트래블 — 사고 직전을 읽는다
/root/ice/tt/travel.py 를 앱 이름 ice-tt-travel 로 만들어 lake.tt.orders.snapshots 에서 세 번째 커밋의 스냅샷 ID 를 찾고, VERSION AS OF 로 그때의 전체 행 수와 부산 행 수를, 지금 표에서 부산 행 수를 세어 /root/ice/tt/out/travel.json 에 {"snapshot_id", "rows_before", "busan_before", "busan_after"} 로 쓰세요.
VERSION AS OF 는 그 스냅샷의 매니페스트 리스트를 읽을 뿐입니다. 사고 전 파일이 아직 디스크에 있으니 그대로 읽힙니다. 스냅샷 ID 는 19자리 정수라 손으로 옮기지 말고 스크립트에서 읽어 쓰세요.
태그 — 시점에 이름과 보존 기간을
/root/ice/tt/tag.py 를 앱 이름 ice-tt-tag 로 만들어 3단계의 스냅샷에 ALTER TABLE lake.tt.orders CREATE TAG before_accident AS OF VERSION <ID> RETAIN 7 DAYS 로 태그를 붙이세요.
태그는 metadata 의 refs 에 이름·스냅샷 ID·max-ref-age-ms 로 들어갑니다. RETAIN 7 DAYS 는 604,800,000ms 입니다. 태그가 가리키는 스냅샷은 만료 대상에서 빠집니다. 채점기는 refs 의 세 값을 봅니다.
롤백 — 포인터만 옮긴다
/root/ice/tt/rollback.py 를 앱 이름 ice-tt-rollback 으로 만들어 태그 before_accident 가 가리키는 스냅샷으로 CALL lake.system.rollback_to_snapshot('lake.tt.orders', <ID>) 를 부르세요.
롤백은 새 스냅샷을 만들지 않고 main 이 가리키는 스냅샷만 바꿉니다. 사고 스냅샷은 snapshots 목록에 그대로 남고, main 이 지나온 길(snapshot-log)에 '사고 → 사고 직전' 이 기록됩니다. 채점기는 그 기록과 사고 스냅샷이 남아 있는지를 봅니다.
브랜치에 먼저 쓴다
/root/ice/tt/branch.py 를 앱 이름 ice-tt-branch 로 만들어 ALTER TABLE lake.tt.orders CREATE BRANCH fix 뒤 2026-03-04 파일을 writeTo("lake.tt.orders.branch_fix").append() 로 fix 에만 쓰세요.
브랜치는 만들 때의 main(되돌린 스냅샷)에서 갈라집니다. fix 에 커밋하면 fix 만 앞으로 가고 main 은 그대로라, 읽는 사람들은 3월 4일 자료를 아직 보지 않습니다. 채점기는 fix 의 머리가 되돌린 스냅샷을 부모로 두고 3월 4일 행 수를 더했는지 봅니다.
발행 — main 을 앞당긴다
/root/ice/tt/publish.py 를 앱 이름 ice-tt-publish 로 만들어 CALL lake.system.fast_forward('lake.tt.orders', 'main', 'fix') 를 부르세요.
fast_forward 는 main 이 fix 의 조상일 때만 됩니다(그 사이 main 에 다른 커밋이 끼었다면 거절). 새 스냅샷 없이 main 포인터만 fix 의 머리로 옮깁니다. 채점기는 main 과 fix 가 같은 스냅샷을 가리키는지, main 에 부산과 3월 4일이 모두 있는지 봅니다.
되돌리기 절차를 한 장으로
/root/ice/tt/report.md 에 ## 타임트래블 ## 롤백과 태그 ## 브랜치 세 절을 쓰세요. 첫 절에는 3단계의 busan_before 를 숫자로 넣으세요.
새벽에 같은 사고가 났을 때 당직자가 따라 할 순서로 적어 보세요. 만료가 도는 표라면 무엇을 먼저 해야 하는지도.