[FLINK-39740][table-runtime] Do not regress highestSqnAndSizeState on row replace in LinkedMultiSetState#28240
Open
jubins wants to merge 2 commits into
Open
Conversation
… row replace in LinkedMultiSetState LinkedMultiSetState.add() unconditionally wrote the computed newSqn back into highestSqnAndSizeState. In the replace branch, newSqn was set to the existing row's SQN — generally less than the current highSqn — so the write regressed the highest-SQN invariant. The next genuinely new row would then compute newSqn = highSqn + 1, collide with an existing node in sqnToNodeState, and silently corrupt the doubly-linked list.
Collaborator
spuru9
reviewed
May 23, 2026
|
|
||
| @TestTemplate | ||
| public void testAddAfterReplacingNonHighestRow() throws Exception { | ||
| // Regression test for FLINK-39740: replacing an existing row by key must not regress |
Contributor
There was a problem hiding this comment.
nit: this jira reference is not needed.
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.
What is the purpose of the change
Fixes FLINK-39740 — in
LinkedMultiSetState,highestSqnAndSizeStatetracks the highest sequence number ever assigned to a row in the doubly-linked list. It must grow monotonically, since new rows compute their SQN ashighSqn + 1. However,LinkedMultiSetState.add()wrote the computednewSqnback intohighestSqnAndSizeStateunconditionally — including in the replace branch, wherenewSqnis set to the existing row's SQN (which is generally less than the currenthighSqn). The next genuinely new row would then computenewSqn = staleHighSqn + 1and collide with an existing node insqnToNodeState, silently overwriting it. The doubly-linked list is then corrupt: iteration returns the wrong rows, and downstream operators reading from this state observe missing or stale data.Brief change log
highestSqnAndSizeState.update(MetaSqnInfo.of(newSqn, newSize))call inside theif (isNewRowKey) { ... }block. The replace branch already enforcesnewSqn = rowSqnandnewSize = oldSize, so the prior unconditional write was redundant (state value didn't actually change) and destructive (rowSqn ≤ highSqnregressed the monotonic invariant).Verifying this change
This change is covered by a new regression test in
SequencedMultiSetStateTest:testAddAfterReplacingNonHighestRow— adds three rows with distinct keys (assigning SQNs 0, 1, 2), then replaces the first row (addon an existing key), then adds a fourth new row. The test asserts the iterator returns all four rows in insertion order with the replaced value visible. Before the fix, the replace regressedhighSqnfrom 2 to 0, the fourth row reused SQN 1 and overwrote the second row's node insqnToNodeState, and iteration returned only three rows with the second row missing.Existing tests in
SequencedMultiSetStateTest(testBasicFlow,testAdd,testAppend,testRemove, etc.) continue to pass, confirming the fix does not regress the happy path or the other state-mutation operations.Does this pull request potentially affect one of the following parts
@Public(Evolving): no —LinkedMultiSetStateis annotated@Internal(see line 80 of the class). The class is intended for internal use within Flink's table runtime, as its Javadoc explicitly states.MetaSqnInfoSerializer,NodeSerializer,RowSqnInfoSerializer, andRowDataKeySerializerare all unchanged. Existing checkpointed state can still be read.Documentation
Was generative AI tooling used to co-author this PR?
Generated-by: Claude Opus 4.7