資料工程面試:Iceberg v3 的 row lineage 如何保證穩定行識別?
題幹與適用場景
一張 Iceberg v3 事件表需要支援 CDC、重算和跨快照稽核。團隊希望每行有可追蹤的穩定識別,並能知道最後更新屬於哪次提交。請解釋 row lineage 的欄位、繼承時機、快照提交重試、equality delete 限制和驗證方案。
面試官考察點
- 是否理解
rowid與lastupdatedsequencenumber的繼承,而非寫入時臆造。 - 是否知道
first-row-id、next-row-id和 manifest 的關係。 - 是否能處理 optimistic commit 重試、並發寫入和舊讀取器相容。
- 是否區分 row lineage、業務主鍵、equality delete 與實體檔案清理。
回答前需要釐清的問題
- 要追蹤的是物理行身份、業務實體身份,還是兩者都要?
- 讀取器是否全部支援 Iceberg v3,舊引擎如何降級?
- 更新採用 copy-on-write、merge-on-read 還是 equality delete?
- 稽核要求跨快照重放,還是只需目前表的最新版本?
30 秒回答框架
Iceberg v3 的 row lineage 用 rowid 標識表內行,用 lastupdatedsequencenumber 表示最後更新提交;值在讀取時透過 data file 的 first-row-id、行位置和 manifest sequence number 繼承。寫入階段先生成帶 null 的檔案,提交成功後由 metadata 確定繼承值,因此提交重試必須重新分配 first-row-id。它不等於業務主鍵,也不能讓 equality delete 保留原行 ID。先建立 v2/v3 讀取能力矩陣,再用快照、並發衝突和重試測試驗證。
分步驟深入解答
1. 區分兩種身份
業務主鍵回答「這是什麼實體」;rowid 回答「這張表中的哪一行」。同一實體被刪除後重新寫入,業務鍵可以相同,但 row lineage 不應被誤當成永久實體 ID。稽核系統應同時保留業務鍵、快照 ID 和 row ID。
2. 理解欄位繼承
新行的 rowid 和 lastupdatedsequencenumber 可以在 data file 先寫成 null。讀取時,row ID 由檔案的 first-row-id 加行位置推導,更新時間由 manifest entry 的 sequence number 推導。寫入器不必在提交成功前重寫資料檔。
row_id = data_file.first_row_id + row_position
last_updated = manifest_entry.data_sequence_number3. 處理提交重試
樂觀並發提交失敗後,表的 next-row-id 可能已變化。重試必須重新讀取目前 metadata,重新分配 first-row-id,並重新生成 manifest list;不能重用第一次嘗試的行號範圍。提交日誌記錄 attempt、衝突原因和最終 snapshot ID。
4. equality delete 的邊界
使用 equality delete 的引擎通常不讀取舊資料行就寫入變更,因此無法提供被替換舊行的原始 row ID。規範把這類更新視為舊行被移除、再新增唯一行。需要穩定業務身份時,另行維護業務鍵和變更事件,不能假設 equality delete 自動延續 row lineage。
5. 相容與讀取
v3 引入 row lineage,但舊讀取器可能不了解保留欄位。升級前建立引擎能力矩陣,確認舊讀者看到 null、忽略欄位或直接失敗的行為。對外匯出不要依賴讀者自動推導 row ID,必要時由支援 v3 的服務先物化稽核欄位。
6. 驗證、回滾與清理
測試單次寫入、並發提交、衝突重試、快照回讀、刪除後重寫和 compaction。驗證同一 snapshot 內 row ID 唯一、重試不會重用舊範圍、sequence number 與最終 snapshot 對齊。回滾只切換快照引用,不重寫歷史 row ID;實體檔案清理由快照過期和 orphan cleanup 負責。
高品質示範回答
我會把業務主鍵和 Iceberg row lineage 分開。v3 用 rowid 和 lastupdatedsequencenumber 提供表內行身份和提交順序,它們可由 data file 的 first-row-id、行位置和 manifest sequence number 在讀取時繼承。寫入先保留 null,提交衝突重試時重新讀取 metadata 並重新分配 ID,不能重用舊 manifest。equality delete 不保證延續舊 row ID,所以稽核要保存業務鍵、snapshot ID 和事件。上線前驗證 v2/v3 讀取、並發衝突、快照回讀、compaction 與清理,並把回滾限定為快照引用切換。
常見錯誤
- 把 row ID 當業務主鍵 → 刪除重建後語意錯誤 → 同時保存業務鍵和 snapshot。
- 在寫檔時永久分配 row ID → 重試可能重複或浪費範圍 → 依賴提交階段的繼承。
- 重用衝突提交的 manifest → 使用過期 next-row-id → 每次重試重新讀取 metadata。
- 認為 equality delete 會保留原 row ID → 規範不保證舊行可讀 → 用業務事件追蹤實體。
- 只驗證目前查詢 → 快照和舊讀取器仍可能不相容 → 覆蓋跨快照和能力矩陣。
追問及應對
為什麼不用業務主鍵代替 rowid?
業務鍵可能重複、變更或跨表不唯一;row lineage 是表內物理行身份。兩者服務不同稽核問題,應同時記錄。
提交衝突重試會不會讓 row ID 出現空洞?
可能出現未被最終快照使用的範圍,具體回收策略由實作決定。重點是不能重用已暴露給成功快照的 ID,且最終快照中的 ID 保持唯一。
compaction 會改變 row ID 嗎?
正確實作應透過 lineage 繼承保留行身份;驗證 compaction 前後同一快照語意和稽核映射,不能只比較檔案路徑。