Skip to content

[BUG] Fix delete_partition followed by re-insert silently loses data under NBCC - #19806

Open
zhang-arvin wants to merge 1 commit into
apache:masterfrom
zhang-arvin:fix/nbcc-delete-partition-reinsert-19793
Open

[BUG] Fix delete_partition followed by re-insert silently loses data under NBCC#19806
zhang-arvin wants to merge 1 commit into
apache:masterfrom
zhang-arvin:fix/nbcc-delete-partition-reinsert-19793

Conversation

@zhang-arvin

Copy link
Copy Markdown

Fixes #19793: Under Non-Blocking Concurrency Control, delete_partition followed by re-insert results in silent data loss.

Root Cause

NBCC uses fixed file IDs per bucket. After delete_partition retires the file group, re-inserts use the same fixed file ID, but FileSystemView filters out the retired file group, causing data to be written but invisible.

Fix

When the fixed file ID has been retired by a replacecommit, bump the generation to create a new file ID that no longer matches the retired file group.

@github-actions github-actions Bot added the size:S PR with lines of changes in (10, 100] label Sep 1, 2026

@hudi-agent hudi-agent left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ 🤖 This review was generated by an AI agent and may contain mistakes. Please verify any suggestions before applying.

Thanks for working on this! The PR addresses silent data loss under NBCC when delete_partition is followed by a re-insert, by bumping the NBCC file-id generation when the default file group has been retired by a replacecommit. The mechanism is sound for a single delete/re-insert cycle, but there's one edge case worth double-checking in the inline comment around repeated cycles. Please take a look at any inline comments, and this should be ready for a Hudi committer or PMC member to take it from here. Two small issues worth tidying: a duplicated private method across both partitioner classes, and a magic-number generation bump.

// (e.g. delete_partition), bump the generation so the new file group id
// no longer matches the retired one, avoiding silent data loss.
if (isFileGroupReplaced(partitionPath, fileId)) {
fileId = BucketIdentifier.newBucketFileIdForNBCC(bucketIdStr, 1);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Hardcoding the bump to generation 1 seems to only cover a single delete_partition + re-insert cycle. On a second cycle, delete_partition retires the now-active gen1, so getAllReplacedFileGroups returns {gen0, gen1} — then this re-inserts to gen1 again, which is also retired, and we're back to silent data loss. Could you loop to the first generation that isn't in the replaced set instead, e.g. int gen = 0; String fileId = newBucketFileIdForNBCC(bucketIdStr, gen); while (isFileGroupReplaced(partitionPath, fileId)) { fileId = newBucketFileIdForNBCC(bucketIdStr, ++gen); }? @nsivabalan does that match your read of how repeated delete_partition cycles accumulate in the replaced set under NBCC?

⚠️ AI-generated; verify before applying. React 👍/👎 to flag quality.

updatePartitionPathFileIds, isOverwrite, isNonBlockingConcurrencyControl, replacedPartitionFileIds);
}

private Map<String, Set<String>> computeReplacedFileIds(HoodieTable table) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 nit: computeReplacedFileIds is copy-pasted verbatim into both partitioner classes — could you move it up to the base class (which already owns replacedPartitionFileIds) or extract it into a small static helper so there's only one copy to maintain?

⚠️ AI-generated; verify before applying. React 👍/👎 to flag quality.

String fileId = BucketIdentifier.newBucketFileIdForNBCC(bucketIdStr);
// When the default generation file group has been retired by a replacecommit
// (e.g. delete_partition), bump the generation so the new file group id
// no longer matches the retired one, avoiding silent data loss.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 nit: the literal 1 is a bit opaque — a named constant like NEXT_GENERATION (or even a brief inline comment clarifying it's always generation 0 + 1) would make the intent clearer to a future reader.

⚠️ AI-generated; verify before applying. React 👍/👎 to flag quality.

@hudi-bot

hudi-bot commented Sep 1, 2026

Copy link
Copy Markdown
Collaborator

CI report:

Bot commands @hudi-bot supports the following commands:
  • @hudi-bot run azure re-run the last Azure build
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:S PR with lines of changes in (10, 100]

3 participants