Skip to content

MDEV-41036 buf_page_peek_if_young() does not properly compute and wra… - #5678

Open
iMineLink wants to merge 1 commit into
11.8from
11.8-MDEV-41036
Open

iMineLink wants to merge 1 commit into
11.8from
11.8-MDEV-41036

Conversation

@iMineLink

Copy link
Copy Markdown
Contributor

…p page age in young calculation

buf_page_t::freed_page_clock is a 31-bit bitfield holding the low bits of buf_pool.freed_page_clock. buf_page_peek_if_young() evaluated the condition now < stamp + window in size_t arithmetic, which failed to account for wraparound within the 31-bit clock space.

When the global clock wrapped past a stamp (particularly when stamp was high, near 2^31), the comparison evaluated to true for an extended period even though the page was older than the window. During these wraparound windows, pages were falsely reported as young.

Because returning true causes InnoDB to skip moving pages to the MRU head (to reduce lock contention), these falsely "young" pages were not promoted.
As a result, active/hot pages could sink into the old portion of the LRU list and be evicted prematurely. Additionally, buf_read_ahead_random() over-counted recently accessed pages during wraparound intervals.

Compute age as (now - stamp) & clock_mask using 31-bit modular arithmetic and compare age < window. A page then cleanly leaves the young window after the intended number of evictions regardless of clock wraparound.

…p page age in young calculation

buf_page_t::freed_page_clock is a 31-bit bitfield holding the low bits
of buf_pool.freed_page_clock. buf_page_peek_if_young() evaluated the
condition now < stamp + window in size_t arithmetic, which failed to
account for wraparound within the 31-bit clock space.

When the global clock wrapped past a stamp (particularly when stamp was
high, near 2^31), the comparison evaluated to true for an extended
period even though the page was older than the window. During these
wraparound windows, pages were falsely reported as young.

Because returning true causes InnoDB to skip moving pages to the MRU
head (to reduce lock contention), these falsely "young" pages were not
promoted.
As a result, active/hot pages could sink into the old portion of the LRU
list and be evicted prematurely. Additionally, buf_read_ahead_random()
over-counted recently accessed pages during wraparound intervals.

Compute age as (now - stamp) & clock_mask using 31-bit modular
arithmetic and compare age < window. A page then cleanly leaves the
young window after the intended number of evictions regardless of clock
wraparound.
@iMineLink
iMineLink requested review from dr-m and a balanced review from Copilot September 14, 2026 13:57
@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The wraparound and threshold boundaries need regression coverage.

Get a fresh assessment by requesting another Copilot review.

Pull request overview

Fixes InnoDB LRU youth detection across the 31-bit eviction-clock wraparound.

Changes:

  • Computes page age using 31-bit modular subtraction.
  • Preserves the existing young-window threshold.
File summaries
File Description
storage/innobase/include/buf0buf.inl Corrects wraparound handling in buf_page_peek_if_young().
Review details
  • Files reviewed: 1/1 changed files
  • Comments generated: 1
  • Review effort level: Balanced

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

buf_pool.freed_page_clock, so the age must be computed modulo 2^31. */
constexpr uint32_t CLOCK_MASK= (1U << 31) - 1;
const uint32_t now= uint32_t(buf_pool.freed_page_clock) & CLOCK_MASK;
const uint32_t age= (now - uint32_t(bpage->freed_page_clock)) & CLOCK_MASK;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Development

Successfully merging this pull request may close these issues.

4 participants