-
Type:
Bug
-
Resolution: Fixed
-
Priority:
Major - P3
-
Affects Version/s: None
-
Component/s: Cache and Eviction
-
None
-
Storage Engines - Transactions
-
614.42
-
SE Transactions - 2026-11-06
-
1
eviction=(cache_tolerance_for_app_eviction=N) is documented as a tolerance on eviction_dirty_trigger and eviction_updates_trigger (dist/api_data.py:833-840). Between the trigger and trigger × (1 + N/100), application threads assist in eviction step by step (__evict_is_session_cache_trigger_tolerant, src/evict/evict_inline.h:768-851). The tolerance does not cover eviction_trigger. With the default incremental_app_eviction=false, the tolerance is never applied. Line numbers reference develop at 50c032ba6.
Location of the check in __wt_evict_app_assist_worker_check (src/evict/evict_inline.h:871-1001):
- :952-954 calls __wt_evict_needed(session, busy, readonly, true, &pct_full) and returns if it returns false.
- :972-979 overwrites pct_full with the cache fill percentage from __wt_evict_clean_needed only when incremental_app_eviction=true and the eviction trigger is not exceeded.
- :985-991 calls __evict_is_session_cache_trigger_tolerant only if pct_full <= evict->eviction_trigger. This is the only call to this function.
Why the condition at :985 is false without incremental_app_eviction: _wt_evict_needed (:587-675) sets pct_full via _wti_evict_threshold_pct (:558-566, called at :662-665):
pct_full = MAX(0, 100 - MIN(eviction_trigger - pct_clean,
dirty_trigger - pct_dirty,
updates_trigger - pct_updates))
__wt_evict_needed returns clean_needed || updates_needed || (!busy && dirty_needed) (:674). When it returns true, at least one usage exceeds its trigger, so the minimum is negative and pct_full > 100. Because eviction_trigger cannot exceed 100 (src/evict/evict_conn.c:28-41, :76-79), pct_full <= eviction_trigger is always false. The disaggregated storage branch for followers and role changes (:635-654) sets pct_full = 100 - (eviction_trigger - pct_clean) and returns clean_needed, producing the same result. The test added by WT-18211 (test/catch2/misc_tests/test_evict_needed_pct_full.cpp) verifies this property of pct_full.
History:
WT-15563 (6db8dcb35, PR #12442) added the condition in its current form, with the same pct_full formula and the preceding incremental branch. WT-15690, WT-16612, and WT-18211 did not modify it. The same condition exists in mongodb-8.2 (src/evict/evict_inline.h:834) and mongodb-8.0 (src/include/cache_inline.h:683 at cd0025dd3). Because mongodb-8.0 lacks the incremental_app_eviction branch entirely, the tolerance has no effect there in any configuration.
Affected users:
Deployments configuring cache_tolerance_for_app_eviction to a non-zero value without incremental_app_eviction=true (for example through wiredTigerEngineRuntimeConfig or storage.wiredTiger.engineConfig.configString). The tolerance does nothing there, while the cache: cache tolerance configured statistic (WT-16453) reports it as set. WT-16453 notes Atlas clusters running with a non-zero tolerance. mongod does not set either option by default.
Proposed fix
Check the eviction trigger directly, and only when the tolerance is non-zero:
uint8_t cache_tolerance = __wt_atomic_load_uint8_relaxed( &conn->cache->cache_eviction_controls.cache_tolerance_for_app_eviction); if (cache_tolerance != 0 && !__wt_evict_clean_needed(session, NULL) && __evict_is_session_cache_trigger_tolerant(session, cache_tolerance)) return (0);
With incremental_app_eviction=true, this matches current behavior (cache fill percentage within the eviction trigger). When N=0, it avoids calling __wt_evict_clean_needed. Comparing pct_full with 100 + N instead would mix units (percent of cache versus percent of a trigger) and would allow the tolerance to apply above eviction_trigger.
Test
test/suite/test_cache_tolerance01.py: an uncommitted transaction holds about 22% of a 200MB cache dirty with eviction_dirty_trigger=20. A read-committed reader with cache_max_wait_ms=500 searches another file, and application_cache_ops shows whether it was pulled into eviction. Scenarios:
- N=0: reader assists.
- N=100: reader does not assist (fails on develop, passes with the fix).
- N=100 with eviction_trigger=20: reader assists (fails if the eviction trigger check is omitted from the fix).
Separate observations, not part of this ticket:
- busy && pct_full < 100.0 at src/evict/evict_inline.h:960 is unreachable for the same reason.
- WT_CONNECTION::reconfigure does not clear incremental_app_eviction, prefer_scrub_eviction, and skip_update_obsolete_check once set (src/evict/evict_conn.c:286-292, :306-308).
- search and search_near in autocommit with cache_max_wait_ms retry WT_ROLLBACK in API_RETRYABLE without waiting (src/cursor/cur_file.c:314).
Pull request: https://github.com/wiredtiger/wiredtiger/pull/14942