morningman opened a new pull request, #69952:
URL: https://github.com/apache/doris/pull/69952

   ### What problem does this PR solve?
   
   Issue Number: None
   
   Related PR: #65810
   
   Problem Summary:
   
   **In short:** a changelog tablet that has nothing to compact, and on which 
no compaction has succeeded for `pick_rowset_to_compact_interval_sec` (a day by 
default), can abort the BE. Cumulative compaction then moves the cumulative 
point to just after the start of the last candidate, and the candidates of a 
changelog tablet start from version 0, so the new point can be smaller than the 
current one and `Tablet::set_cumulative_layer_point` fails its CHECK. This PR 
keeps changelog tablets out of that fallback; their own policy does not need it.
   
   #### Background
   
   - When `CumulativeCompaction::pick_rowsets_to_compact` picks nothing and 
neither a base nor a cumulative compaction has succeeded on the tablet for 
`pick_rowset_to_compact_interval_sec`, it falls back: if one candidate overlaps 
it compacts every candidate at once, otherwise it moves the cumulative point to 
`candidate_rowsets.back()->start_version() + 1`. This keeps base compaction, 
which reads the rowsets below the point, going on a tablet that gets no new 
rowsets.
   - For an ordinary tablet the candidates start at the cumulative point, so 
the new point is always above the old one.
   - Since #65810 a changelog tablet compacts through the same 
`CumulativeCompaction`, with `ChangelogCumulativeCompactionPolicy`. Its 
candidates start from version 0 
(`Tablet::pick_candidate_rowsets_to_changelog_compaction`), and its point means 
something else: it ends the prefix of compact-enough LMax rowsets, which the 
policy quick-merges instead of rewriting. The policy moves the point itself 
(`calculate_cumulative_point`, `update_cumulative_point`), the tablet is not 
scheduled for base compaction (`Tablet::can_do_compaction` allows only 
`CHANGELOG_COMPACTION`), and the policy has a time trigger of its own 
(`changelog_compaction_time_threshold_seconds` after the last successful 
compaction). TTL cleanup is picked before the policy, in 
`Compaction::pick_expired_changelog_rowset`.
   
   #### The problem, and what it cost
   
   - The point the fallback sets for a changelog tablet can be below the 
current one, and `Tablet::set_cumulative_layer_point` CHECKs that it never goes 
backwards, so the BE aborts. Two common layouts get there:
     - a tablet compacted into the single LMax rowset `[0-5]` has its point at 
6; a day later the fallback sets it to `0 + 1 = 1`;
     - once `[0-5]` and the rowsets after it have expired, a TTL cleanup turns 
them into one empty rowset `[0-N]` and leaves the point at 6 
(`update_cumulative_point` skips an empty output); a day later, the same.
   
     The first one survives a restart: the point is computed from the rowsets 
again and the success times start over, so the BE aborts again a day later. 
Seen on a local cluster, a day after the last compaction of the tablet: `Check 
failed: new_point == Tablet::K_INVALID_CUMULATIVE_POINT || new_point >= 
_cumulative_point Unexpected cumulative point: 1, origin: 2` in 
`CumulativeCompaction::pick_rowsets_to_compact`.
   - If one candidate overlaps, for example the output of a quick merge, the 
fallback hands every candidate to one compaction: the whole tablet from version 
0, rowsets of every level, past `changelog_level_compaction_max_deltas`.
   - A day without compaction is the normal state of a changelog tablet that is 
no longer written, e.g. in an old partition of a table partitioned by time.
   
   #### How this PR fixes it
   
   - In `CumulativeCompaction::pick_rowsets_to_compact` the fallback no longer 
applies to a changelog tablet: it gets `CUMULATIVE_NO_SUITABLE_VERSION`, as 
before the interval has passed, and keeps its point.
   - The first-time initialization of the success times stays, since the time 
trigger of the changelog policy reads the cumulative one.
   - Ordinary tablets are unchanged. Cloud mode is not affected: 
`CloudCumulativeCompaction` has no such fallback.
   
   #### Results
   
   | Changelog tablet with nothing to compact, no compaction for 
`pick_rowset_to_compact_interval_sec` | Before this PR | After this PR |
   | --- | --- | --- |
   | One candidate overlaps (e.g. a quick-merge output) | Every candidate 
compacted at once | Nothing compacted |
   | No candidate overlaps, the last one starts two or more versions below the 
point (e.g. only `[0-5]` left, point 6) | Point set back (to 1), BE aborts on 
the CHECK | Point kept, nothing compacted |
   | No candidate overlaps, otherwise | Point moved to just after the start of 
the last candidate | Point kept, nothing compacted |
   | A tablet without changelog | Fallback as above | Unchanged |
   
   #### Classes, and how they call each other
   
   - `CumulativeCompaction::pick_rowsets_to_compact`: the one changed condition.
   - 
`TestChangelogCumulativeCompactionPolicy.idle_tablet_keeps_cumulative_point`: 
the new case.
   
   ```
   CumulativeCompaction::prepare_compact
     |-- Tablet::calculate_cumulative_point        changelog policy: end of the 
compact-enough LMax prefix
     `-- CumulativeCompaction::pick_rowsets_to_compact
           |-- Tablet::pick_candidate_rowsets_to_cumulative_compaction
           |     `-- changelog tablet: 
pick_candidate_rowsets_to_changelog_compaction, from version 0
           |-- Compaction::pick_expired_changelog_rowset           TTL cleanup
           |-- ChangelogCumulativeCompactionPolicy::pick_input_rowsets
           `-- nothing picked, no compaction for 
pick_rowset_to_compact_interval_sec
                 |-- changelog tablet (new): CUMULATIVE_NO_SUITABLE_VERSION, 
point kept
                 `-- other tablets: compact every candidate if one overlaps,
                                    else 
Tablet::set_cumulative_layer_point(start of the last candidate + 1)
   ```
   
   Not changed: the changelog policy, how its candidates are picked, and 
`Tablet::set_cumulative_layer_point`.
   
   ### Release note
   
   Fix a BE crash ("Unexpected cumulative point") on a tablet of a table with 
changelog enabled that had nothing to compact for a day.
   
   ### Check List (For Author)
   
   - Test <!-- At least one of them must be included. -->
       - [ ] Regression test
       - [x] Unit Test
       - [ ] Manual test (add detailed scripts or steps below)
       - [ ] No need to test or manual test. Explain why:
           - [ ] This is a refactor/code format and no logic has been changed.
           - [ ] Previous test can cover this change.
           - [ ] No code files have been changed.
           - [ ] Other reason <!-- Add your reason?  -->
   
       
`TestChangelogCumulativeCompactionPolicy.idle_tablet_keeps_cumulative_point`: a 
changelog tablet with only `[0-1]` left, the point at 2 and no compaction for 
longer than `pick_rowset_to_compact_interval_sec`. `pick_rowsets_to_compact` 
returns `CUMULATIVE_NO_SUITABLE_VERSION`, picks nothing and keeps the point, 
for an overlapping and for a non-overlapping rowset. Without the fix the 
overlapping case picks every candidate, and the non-overlapping one aborts with 
`Unexpected cumulative point: 1, origin: 2`, the message seen on the cluster.
   
       With the fix the 13 compaction and changelog suites around 
`pick_rowsets_to_compact` pass, 141 cases: 
`TestChangelogCumulativeCompactionPolicy`, 
`TestSizeBasedCumulativeCompactionPolicy`, 
`TestTimeSeriesCumulativeCompactionPolicy`, `CumulativeCompactionTest`, 
`TestBaseCompaction`, `OrderedDataCompactionTest`, `VerticalCompactionTest`, 
`CompactionTaskTest`, `CompactionScoreTest`, `CompactionMetricsTest`, 
`ChangelogTtlTest`, `ChangelogVmergeCompactionTest` and 
`RowTtlFullCompactionTest`. They ran on a local ASAN UT build (macOS) whose 
storage, tablet and compaction sources are those of master; both changed files 
also compile against master.
   
   - Behavior changed:
       - [ ] No.
       - [x] Yes. <!-- Explain the behavior change -->
   
       A changelog tablet that has had nothing to compact for 
`pick_rowset_to_compact_interval_sec` keeps its cumulative point and starts no 
compaction, instead of aborting the BE, moving its point or compacting all its 
rowsets at once.
   
   - Does this need documentation?
       - [x] No.
       - [ ] Yes. <!-- Add document PR link here. eg: 
https://github.com/apache/doris-website/pull/1214 -->
   
   ### Check List (For Reviewer who merge this PR)
   
   - [ ] Confirm the release note
   - [ ] Confirm test cases
   - [ ] Confirm document
   - [ ] Add branch pick label <!-- Add branch pick label that this PR should 
merge into -->
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to