Skip to content

branch-4.1: [fix](fe) avoid concurrent tablet stat iteration failures #63298#63560

Open
github-actions[bot] wants to merge 1 commit into
branch-4.1from
auto-pick-63298-branch-4.1
Open

branch-4.1: [fix](fe) avoid concurrent tablet stat iteration failures #63298#63560
github-actions[bot] wants to merge 1 commit into
branch-4.1from
auto-pick-63298-branch-4.1

Conversation

@github-actions
Copy link
Copy Markdown
Contributor

Cherry-picked from #63298

### What problem does this PR solve?

Issue Number: #59138

Problem Summary:

TabletStatMgr.runAfterCatalogReady() is a periodic master-FE daemon that
iterates every tablet/replica to pull statistics. When DDL runs
concurrently with this daemon, two races fire:

Iteration race (CME). MaterializedIndex.tablets and LocalTablet.replicas
were plain ArrayLists whose getters returned the internal list. A
concurrent addTablet / addReplica / deleteReplica (clone, repair, schema
change, restore, report handler) during iteration triggered the
fail-fast iterator and threw ConcurrentModificationException.
TOCTOU race. In updateTabletStat, a getTabletMeta(id) != null check is
followed by getReplica(id, beId). If the tablet is removed in between,
getReplica hits Preconditions.checkState(...) and throws
IllegalStateException.
When the daemon throws, the current cycle leaves stale
tablet/partition/table sizes and skewed MetricRepo metrics until the
next cycle.

Solution:
Close the CME race for good with copy-on-write via a volatile snapshot.
A first attempt returned a defensive copy (Lists.newArrayList(...)), but
the copy itself iterates the source list and can still CME mid-copy —
the window shrank but did not close. This PR instead:

Makes LocalTablet.replicas and MaterializedIndex.tablets volatile.
Writers (addReplica / deleteReplica / deleteReplicaByBackendId /
addTablet / clearTabletsForRestore) are synchronized, build a new list,
and atomically swap the volatile reference — they never mutate a list in
place.
Readers (getReplicas() / getTablets()) do a single volatile read and
return an immutable snapshot (Collections.unmodifiableList). Iteration
is lock-free and can never CME, and the hot read path no longer copies
elements.
synchronized on writers is required (not just volatile) because some
write paths do not hold the OlapTable write lock — verified by tracing
call sites: InternalCatalog.createPartitionWithIndices and
RestoreJob.resetPartitionForRestore call addReplica/addTablet without
the table write lock, so concurrent writers are real and a plain
volatile field would allow lost updates. Writers are infrequent (DDL /
repair / restore), so the lock cost is negligible; reads stay lock-free.

TOCTOU race is handled by catching IllegalStateException around
getReplica (kept from the original fix) and counting the skip via a new
TabletStatMgr.staleTabletStatSkipped counter, which makes the race
observable (>0 proves the window was actually hit) instead of relying
solely on log scraping.

Cloud path: CloudTabletStatMgr.updateStatInfo iterates
tablet.getReplicas() and is covered by the same snapshot fix; its
updateTabletStat uses getReplicasByTabletId (locked, returns empty list,
no checkState) and is already safe.


### Release note

None

### Check List (For Author)

- Test <!-- At least one of them must be included. -->
    - [ ] Regression test
    - [ ] 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.
    - [ ] Yes. <!-- Explain the behavior change -->

- Does this need documentation?
    - [ ] No.
- [ ] Yes. <!-- Add document PR link here. eg:
apache/doris-website#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 -->

---------

Co-authored-by: morningman <yunyou@selectdb.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot requested a review from yiguolei as a code owner May 23, 2026 08:04
@hello-stephen
Copy link
Copy Markdown
Contributor

Thank you for your contribution to Apache Doris.
Don't know what should be done next? See How to process your PR.

Please clearly describe your PR:

  1. What problem was fixed (it's best to include specific error reporting information). How it was fixed.
  2. Which behaviors were modified. What was the previous behavior, what is it now, why was it modified, and what possible impacts might there be.
  3. What features were added. Why was this function added?
  4. Which code was refactored and why was this part of the code refactored?
  5. Which functions were optimized and what is the difference before and after the optimization?

@hello-stephen
Copy link
Copy Markdown
Contributor

run buildall

@hello-stephen
Copy link
Copy Markdown
Contributor

FE Regression Coverage Report

Increment line coverage 52.63% (60/114) 🎉
Increment coverage report
Complete coverage report

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants