[flink] Fix GlobalFullCompactionSinkWrite re-reading snapshots on every checkpoint after a full compaction - #9959
Merged
JingsongLi merged 1 commit intoSep 19, 2026
Conversation
…ry checkpoint after a full compaction When checkSuccessfulFullCompaction finds the COMPACT snapshot of a submitted full compaction it clears writtenBuckets up to and including that identifier, but clears commitIdentifiersToCheck with the exclusive headSet(commitIdentifier), so the identifier it just found stays in the set. From then on every prepareCommit walks the snapshot files from the latest one down to that COMPACT snapshot again, until the next full compaction replaces the identifier and the walk starts over. Use the inclusive headSet(commitIdentifier, true), matching the headMap call next to it. Add a test that drives the writer through a full compaction and asserts that later prepareCommit calls open nothing older than the latest snapshot.
Contributor
Author
|
Repro without any code change (master 8b7fbff): stream into a primary-key table created with CREATE TABLE T (id INT, v STRING, PRIMARY KEY (id) NOT ENFORCED) WITH (
'bucket' = '1',
'changelog-producer' = 'full-compaction',
'full-compaction.delta-commits' = '10'
);with a 500 ms checkpoint interval and |
Contributor
|
+1 |
XiaoHongbo-Hope
pushed a commit
that referenced
this pull request
Sep 20, 2026
…ry checkpoint after a full compaction (#9959)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Purpose
fix #9958
With
changelog-producer=full-compactionthe Flink writer (GlobalFullCompactionSinkWrite) keeps a set of checkpoint identifiers whose full compaction it still has to confirm. On everyprepareCommitwhile that set is non-empty,checkSuccessfulFullCompactionwalks the snapshot files from the latest one downwards (one LATEST hint read, one EARLIEST hint read, then one snapshot file per step) until it finds the COMPACT snapshot of one of those identifiers. When it finds it, it clearswrittenBuckets.headMap(id, true)(inclusive) butcommitIdentifiersToCheck.headSet(id)(exclusive), so the identifier it just found stays in the set. From then on every checkpoint walks the snapshots again, down to that COMPACT snapshot, until the next full compaction replaces the identifier and the walk starts over. The set never becomes empty once the first full compaction has happened. On a 60-checkpoint MiniCluster run withfull-compaction.delta-commits=10that is 50 snapshot walks and about 280 snapshot file reads plus 100 hint file reads from this check, against 5 walks, 5 reads and 10 hint reads with the fix.I measured it on a local MiniCluster (Flink 1.20.1, parallelism 1, checkpoint interval 500 ms, datagen source into a primary-key table with
changelog-producer=full-compactionandfull-compaction.delta-commits=10, warehouse on aLocalFileIOsubclass that counts opened snapshot files and checks the call stack). Over 60 checkpoints, unmodified master (36760b4) rancheckSuccessfulFullCompactionon all 50 checkpoints after the first full compaction and read 277 to 283 snapshot files plus 100 hint files from it (six runs), a sawtooth of 1, 2, ..., 10 snapshot files per checkpoint, 5.6 per checkpoint on average, 11 at the peak. The writer also loggedFound full compaction snapshot #... with identifier ...at DEBUG level 50 times for 6 full compactions. With the fix the same run does 5 traversals and reads 5 snapshot files and 10 hint files from that method, one traversal per observed full compaction (the sixth compaction lands on the last checkpoint), and logs the DEBUG line 5 times. Snapshot file reads from all origins in the MiniCluster JVM drop from 453 to 462 down to 181 to 184. Every writer subtask does this, so on a real job the extra snapshot-directory reads per checkpoint scale with the parallelism and withfull-compaction.delta-commits(up to that many snapshot files per subtask per checkpoint, each a GET on an object store).The fix is the inclusive
headSet(commitIdentifier, true), matching theheadMap(commitIdentifier, true)on the line above and the otherheadSet/headMapcalls in paimon-flink.Tests
New
GlobalFullCompactionSinkWriteTest#testStopsCheckingSnapshotsAfterFullCompactionIsObserved: drives the writer through four checkpoints withdeltaCommits=4(the fourth triggers the full compaction and commits its COMPACT snapshot), lets checkpoint 5 observe it, and records which snapshot filesprepareCommitopens for checkpoints 6 and 7 through aLocalFileIOsubclass. The table writer opens the latest snapshot once to find its last committed identifier, so the assertion is that nothing older than the latest snapshot is opened. Without the fix checkpoint 6 also opens snapshot 5 (the COMPACT snapshot of checkpoint 4) and the test fails:[snapshot files read by prepareCommit for checkpoint 6] Expecting: [6L, 5L, 6L] to be subset of [6L] but found these extra elements: [5L].FullCompactionFileStoreITCasestill passes.The MiniCluster measurement above was run six times per variant against the unmodified and the fixed module jar; the numbers were stable across runs.