Repository navigation
[core] Do not expire the snapshot the LATEST hint points to - #10323
dev-donghwan wants to merge 3 commits into
Conversation
JingsongLi
left a comment
There was a problem hiding this comment.
-1 here will another io.
|
Thanks for the review, @JingsongLi! You're right, I overlooked that I've reverted the Could you take another look when you have time? |
|
Reviewed head [P1] Recover commit-user deduplication before allowing the commit to proceed (
This is reachable in Flink's batch committer restart path: I reproduced this with an append table ( Please make the commit-user lookup recover from the missing hint as well before concluding that a commit is new, and add replay coverage for both conflict-check modes. A failure-only fallback can preserve the normal-path I/O cost. There is also a remaining scope gap: Validation: |
|
Thanks for the detailed review, @JingsongLi. You're right about both points. I reproduced the duplicate commit on I think I took the wrong approach with this PR, so before pushing anything I'd like to ask for your view as the original author of the hint files. The current direction is to fix the read side. To continue with it, every caller that relies on the latest snapshot id would have to handle a hint that points to an expired snapshot.
Fixing each of these one by one would make the change much larger, and each fix could bring another side effect like these. So instead of the read side, I looked at the side that deletes snapshots. The stale state only appears when expiration deletes the snapshot the Proposal Snapshot expiration does not expire the snapshot the
If hint writes keep failing In our incident, hint writes failed because of a broken TaskManager, which Paimon cannot prevent. What Paimon can avoid is turning that into a permanent outage: the TaskManager problem lasted about 6 minutes, while the table stayed stuck for two days until I ran 30 commits with every Today the only trace of this is the generic I also tried letting expiration rewrite the Measured comparison
All cells come from running the same probe on the four variants, except the rollback procedures, which are from reading the code. 1. A table whose
2. A table that is already in the stale state
With B in place, A only runs on tables that are already stale. There it brings back commits but turns other failures into silently wrong results, and it does not fix the rest. So I'd go with B alone. Tests The tests produce the stale hint through real commits with Does this direction match how you see the hint files, and would you like the extra warning in the commit retry path as part of this PR? If so, I'll update the PR accordingly. |
|
The expiration-side direction (B alone, with the read-side recovery reverted) looks preferable for this PR. It preserves the invariant used by the existing readers and commit-user deduplication, and keeps recovery of already-broken tables as an explicit repair operation. The current Please implement the protection as a cap on the entire expiration prefix, like the consumer boundary, rather than skipping only snapshot N. Keep the contiguous suffix from the hinted snapshot onward: retaining N while deleting N+1 would still make One detail needs care: The expiration warning is useful; include the hinted ID, actual latest ID and retained boundary, and avoid repeating it without bound. A concise warning on the retry path that finds the snapshot already committed is also reasonable, with the completed snapshot ID and conditional wording such as “LATEST may not have been updated.” Keep it off the normal successful commit path and avoid claiming a failed hint write when the preceding exception does not establish that. Please update the PR and its tests to B before treating the current findings as resolved. |
findLatest trusts the LATEST hint as long as the snapshot after it does not exist. When hint writes fail for longer than the snapshot retention, expiration deletes the hinted snapshot and the one after it, and findLatest then returns a snapshot that no longer exists. Commits fail before they can rewrite the hint, so the table cannot recover without fixing LATEST by hand. Keep the snapshot the LATEST hint points to and all later ones during expiration, similar to the snapshots kept for consumers. Read the hint strictly and expire nothing when it cannot be read or when the hinted snapshot is missing, so that expiration never deletes data files of snapshots it keeps. Skip this when the catalog manages the snapshots of the table, since the hint is not written then. Also warn once per hint when expiration keeps snapshots because of it, and warn when a commit retry finds its snapshot already committed, since the LATEST hint may not have been updated.
- Keep the snapshot after a missing hinted one, since findLatest still works while it exists, and skip only if both are missing. - Retry reading the hint like readHint, and ignore a hint which is not a positive number like findLatest does. - Warn once while the hint cannot be checked. - Share the condition of catalog managed snapshots in CatalogEnvironment.
…on in the retry warning
d8ef8b9 to
ca5494e
Compare
|
Thanks for the direction. I force-pushed the PR to implement B only, so the read-side What this PR changes
How each of your points is addressed
In addition I handled the case where the hinted snapshot is already missing. Without it, expiring the Behavior changes While the hint is behind, more snapshots than |
|
@dev-donghwan Did you encounter such complex changes in a production environment? In all my years, I’ve never seen such an extreme scenario. |
|
You are right that this is an extreme scenario, and it does not happen often. We did hit it once in production, but it was a coincidence of a configuration issue on our side and an infrastructure issue at the same time. We have fixed that configuration, and I agree it is unlikely to happen again now. Here is what happened, with simplified numbers (
The retry path in step 2 is fixed by #10324. But as long as the snapshot and the hint are written separately, an infrastructure issue between them cannot be ruled out, and when expiration then deletes the snapshot its own hint points to, a transient issue becomes an outage that needs manual repair. This PR only aims to prevent that last step. If you think this case is not worth the change, I will follow your judgment and close the PR. |
Related: #10324 (merged) fixes one way the
LATESThint falls behind (a snapshot rename that throws but has succeeded).Purpose
When writing the LATEST hint keeps failing, the hint stays at an old snapshot while
commits still succeed. For example, a commit whose retry finds that the previous attempt
already committed the snapshot returns success without writing the hint. If snapshot
expiration then deletes the hinted snapshot,
findLatestreturns a missing snapshot, andreads and commits fail until LATEST is fixed by hand.
This PR keeps snapshot expiration from deleting the hinted snapshot and the ones after it,
like the consumer boundary:
deleted, on both the retained-count and the time-retention paths.
apart from an absent one.
kept. If that one is missing too, expiration is skipped.
not protected.
retry finds the snapshot already committed.
Reads and commits are not changed.
Behavior changes
snapshot.num-retained.maxcan be retained,like with consumers, with a warning. They are expired once the hint is updated again.
expire_snapshotsprocedures can expire fewer snapshots or return 0.the window against concurrent commits and rollbacks as small as possible.
Tests
StaleLatestHintTest: hint read and write failures and recovery, commits and rollbacksduring expiration, replaying a committed commit with and without append file checks,
streaming read from latest, incremental read between timestamps, rollback, boundaries
(missing hinted snapshot, hint around the earliest snapshot, data files of a primary key
table), catalog managed snapshots, branches, hint reads on the normal path and warnings.
CommitterOperatorTest: replaying the end-of-input commit in Flink batch mode while theLATEST hint is behind.