SS-148 Iceberg sink, don't attempt commit unless it's definitely not a duplicate - #38441
SS-148 Iceberg sink, don't attempt commit unless it's definitely not a duplicate#38441ublubu wants to merge 10 commits into
Conversation
Claude: on both retrial paths, check for other writers
QA LLM Review1. MEDIUM -- Pre-commit guard only rejects an exactly-equal frontier, so a writer that committed a strict prefix of our batch still produces duplicate rows
The new guard proves "not a duplicate" only when DetailsThe reachable window is a sink version handoff, which is a normal
Suggested fix, after the two existing fatal arms: if last_frontier != *batch_lower {
// Another writer committed inside our batch range. Committing now would
// duplicate [batch_lower, last_frontier). Restart and re-resume instead.
return (
table,
RetryResult::FatalErr(anyhow!(
"Iceberg table '{}' advanced to frontier {:?} inside batch [{}, {}); \
another writer is active.",
conn_table,
last_frontier,
batch_lower.pretty(),
batch_upper.pretty(),
)),
);
}2. MEDIUM --
|
There was a problem hiding this comment.
I think just fix this main issue and it looks ok? Would also take a look at the test setup issue in the LLM review but that's less important to me.
Merge issues probably just from my iceberg stuff last week, should be pretty easy although you'll need to rebase your iceberg-rust changes and update the revision
|
|
||
| ( | ||
| if PartialOrder::less_equal(frontier, &last_frontier) { |
There was a problem hiding this comment.
| if PartialOrder::less_equal(frontier, &last_frontier) { | |
| if PartialOrder::less_equal(frontier, &last_frontier) || PartialOrder::less_than(batch_lower, &last_frontier) { |
I think this should address the issue in the LLM review and catch when another writer has written a partially overlapping batch, as the last frontier should be <= all items in this batch.
Given the generally longer commit intervals for iceberg sinks, this actually seems fairly likely to happen (i.e. the other writer committed 5 seconds ago, so this batch does have a later frontier, but there's still overlap. Thankfully it looks like an easy fix?
| iceberg = { git = "https://github.com/MaterializeInc/iceberg-rust.git", rev = "dedd9231ee88ee979b648e14792878b40e74c20a" } | ||
| iceberg-catalog-rest = { git = "https://github.com/MaterializeInc/iceberg-rust.git", rev = "dedd9231ee88ee979b648e14792878b40e74c20a" } | ||
| iceberg-storage-opendal = { git = "https://github.com/MaterializeInc/iceberg-rust.git", rev = "dedd9231ee88ee979b648e14792878b40e74c20a" } | ||
| # FIXME: This is currently pointing at kynan/pub-commit, a temporary branch. DO NOT MERGE AS-IS. |
There was a problem hiding this comment.
Also just don't forget this lol
replaces #38333
We rely on MaterializeInc/iceberg-rust#7 making the Transaction commit internals public.
Then we reimplement Transaction commit, but without the built-in rebase+retry.
Previously,
iceberg-rustloaded the table from the Catalog on every commit attempt, applying the transaction's actions on top of the latest state of the table.With this PR, Mz loads the table from the Catalog on every commit attempt, but it does not apply the transaction's action on top of the latest state of the table until after it inspects the table state (for funny business like a previously successful attempt or another writer taking over).