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

   ### What problem does this PR solve?
   
   Issue Number: None
   
   Related PR: #46570
   
   Problem Summary:
   
   `BetaRowset::get_segment_num_rows()` loads the row count of each segment 
through `DorisCallOnce<Status>`. `DorisCallOnce` stores the result of the first 
call **whether it succeeded or not**, so if the first load fails, every later 
call returns the same failed `Status` without doing any IO.
   
   A `BetaRowset` object lives as long as its tablet version. If the first load 
hits a transient IO error (e.g. S3 `SlowDown`/503 while reading the segment 
footer), the error is stuck on that rowset until the BE restarts. Compaction on 
merge-on-write tablets needs segment rows for rowid conversion 
(`BetaRowsetReader::get_segment_iterators`), so it keeps failing on that 
rowset. The failure also stops the rowset from ever being compacted away.
   
   We hit this in a cloud cluster. After a burst of S3 503s, compaction on a 
few MOW tablets kept failing every ~5s (`min_compaction_failure_interval_ms`) 
for hours:
   
   - each failure reported the same file path and the same S3 `request_id`;
   - each failed only ~10ms after compaction started, which is too fast for a 
real S3 request;
   - lowering compaction permits did not help, because the cached error is 
returned before any data is read.
   
   Only restarting the BE recovered it.
   
   Queries that go through `ParallelScannerBuilder` call the same function, so 
they can hit the stale error too. The first failure can come from a query as 
well as from compaction.
   
   Segment-level lazy loading does not have this problem: `SegmentLoader` 
checks `Segment::healthy_status()` and reloads an unhealthy cached segment. 
Rowset-level segment rows are the only place without such a fallback.
   
   This PR replaces `DorisCallOnce` with a double-checked `std::atomic<bool>` 
flag and a mutex:
   
   - The flag is set (release) only after a successful load, so a failed load 
is retried by the next caller, and a successful result is still cached.
   - Like `DorisCallOnce`, the fast path reads the flag (acquire) without 
taking the lock. After loading, `_segments_rows` is never modified, so it is 
read without the lock. This matters because `ParallelScannerBuilder` calls this 
for every rowset of every query.
   - `_segments_rows` is cleared at the start of each attempt, so rows left 
over from a failed attempt are never reused.
   
   Rowsets written after #59476 usually take their segment rows from the rowset 
meta and don't read footers here, which makes this less likely on master. 
Rowsets written by older versions still read footers.
   
   ### Release note
   
   Fix compaction and queries repeatedly failing with the same stale error 
after a transient IO error (e.g. S3 SlowDown) while loading segment rows of a 
rowset.
   
   ### 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?  -->
   
   - Behavior changed:
       - [ ] No.
       - [x] Yes. A failed load of segment rows is no longer cached on the 
rowset; the next caller retries it.
   
   - 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