Skip to content

[Bug] Fix data evolution self-merge ABA across rollback snapshot lineage - #9363

Open
zhang-arvin wants to merge 1 commit into
apache:masterfrom
zhang-arvin:fix/data-evolution-self-merge-aba-snapshot
Open

[Bug] Fix data evolution self-merge ABA across rollback snapshot lineage#9363
zhang-arvin wants to merge 1 commit into
apache:masterfrom
zhang-arvin:fix/data-evolution-self-merge-aba-snapshot

Conversation

@zhang-arvin

Copy link
Copy Markdown
Contributor

What changes were proposed in this pull request?

Fix #9352: Data evolution self-merge validates staged row-ID partial updates using base snapshot ID only, not snapshot UUID. A rollback can delete newer snapshots, after which new commits reuse the same numeric snapshot IDs. This allows staged updates from old snapshots to be applied to different replacement snapshots (ABA problem).

Changes

  • DataEvolutionConflictDetection: Add baseSnapshotUuid field and UUID-based lineage validation
    • Fail closed when latestSnapshot.id() < rowIdCheckFromSnapshot (rollback deleted base)
    • Detect missing base snapshot (race with cleanup)
    • ABA detection: compare baseSnapshotUuid with current snapshot UUID at same ID
  • ConflictDetection: Add setRowIdCheckFromSnapshot(Long, String) UUID overload
  • FileStoreCommit / FileStoreCommitImpl: Add UUID overload
  • InnerTableCommit / TableCommitImpl: Add UUID overload
  • ErrorMessages: Add DATA_EVOLUTION_SNAPSHOT_LINEAGE_CONFLICT_MESSAGE

Backward Compatibility

The baseSnapshotUuid field is nullable. Callers that don't pass UUID continue to work with existing behavior (no ABA protection).

Follow-up

Caller layers (Spark PaimonSparkWriter, Flink DataEvolutionMergeIntoAction, BatchWriteBuilderImpl) should be updated to pass the snapshot UUID for full ABA protection.

Related issues

@ArnavBalyan

Copy link
Copy Markdown
Member

Hi @zhang-arvin thanks for the changes the CI is failing, can you PTAL

new RuntimeException(
ErrorMessages.DATA_EVOLUTION_SNAPSHOT_LINEAGE_CONFLICT_MESSAGE));
}
if (baseSnapshotUuid != null

@ArnavBalyan ArnavBalyan Aug 23, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Looks like Spark and Flink are using the single argument offloading causing the method to never get invoked. Would be better to capture and pass the UUID to the overloaded method.

@JingsongLi

Copy link
Copy Markdown
Contributor
  • The newly added (snapshotId, baseSnapshotUuid) validation has not been integrated into the actual call chain. Components such as BatchWriteBuilderImpl:80 and Flink's DataEvolutionMergeIntoAction:428 still pass only the snapshot ID; consequently, the UUID is unavailable in Spark/Flink production paths, the ABA check in DataEvolutionConflictDetection:390 is not executed, and the issue described in the title remains reproducible.
  • The PR does not include regression tests for ABA/rollback scenarios.

Add snapshot UUID-based lineage validation to prevent staged
row-ID partial updates from being applied to wrong snapshots
after a rollback reuses the same numeric snapshot ID.

Three-layer validation in checkForRowIdFromSnapshot:
1. Fail closed when latest snapshot ID < base snapshot ID
   (rollback deleted the update's base snapshot)
2. Detect missing base snapshot (race with concurrent cleanup)
3. ABA detection: compare base snapshot UUID with current
   snapshot UUID at the same ID (different lineage)

The baseSnapshotUuid field is nullable for backward
compatibility. Callers that don't pass UUID get existing
behavior without the ABA protection.

Closes apache#9352
@zhang-arvin
zhang-arvin force-pushed the fix/data-evolution-self-merge-aba-snapshot branch from e102180 to bcfd450 Compare August 24, 2026 03:29
@zhang-arvin

Copy link
Copy Markdown
Contributor Author

Thanks for the review @ArnavBalyan @JingsongLi! Fixed the callers to pass snapshot UUID. Now BatchWriteBuilderImpl, DataEvolutionMergeIntoAction, and DataEvolutionDeleteSink all pass the UUID to rowIdCheckConflict. Added regression tests for ABA detection in ConflictDetectionTest. PTAL.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] Data evolution self-merge can cross rollback snapshot lineage

3 participants