Bug #121037 Bug: Alter_stage::aggregate() skips merge_sort/insert phases due to wrong comparison thresholds
Submitted: 30 Jul 8:58
Reporter: Alice Alice Email Updates:
Status: Open Impact on me:
None 
Category:MySQL Server: Performance Schema Severity:S4 (Feature request)
Version:8.0 OS:Any
Assigned to: CPU Architecture:Any

[30 Jul 8:58] Alice Alice
Description:
  aggregate() advances m_cur_phase per stage with the pattern m_cur_phase < THIS_STAGE, but the
  merge_sort and insert branches compare against the wrong enum value:

  } else if (stage.first == &srv_stage_alter_table_merge_sort) {
    if ((int)m_cur_phase < (int)NOT_STARTED)  { m_cur_phase = SORT; }   // < 0, never true
  } else if (stage.first == &srv_stage_alter_table_insert) {
    if ((int)m_cur_phase < (int)SORT)         { m_cur_phase = INSERT; } // < SORT, wrong
  }

  Enum: NOT_STARTED=0, READ_PK=1, SORT=2, INSERT=3, FLUSH=4, LOG_INDEX=5, LOG_TABLE=6, END=7.

  - merge_sort: < NOT_STARTED (i.e. < 0) is never true → dead branch, m_cur_phase never reaches SORT.
  - insert: should be < INSERT; with the merge_sort fix, once m_cur_phase == SORT (2), < SORT is false
  → insert also skipped. The aggregated phase jumps straight to LOG_INDEX.

How to repeat:
  performance_schema.events_stages_current may never report stage/innodb/alter table (merge sort) /
  (insert) as the aggregated phase after sub-builders are aggregated; the phase label skips to log 
  apply index. Only the phase label is affected — WORK_COMPLETED/WORK_ESTIMATED are accumulated
  independently and remain correct. No crash.

Suggested fix:
  Compare against the stage being assigned in all four branches:

    if ((int)m_cur_phase < (int)READ_PK)   { m_cur_phase = READ_PK;   ... }
    if ((int)m_cur_phase < (int)SORT)      { m_cur_phase = SORT;      ... }  // was < NOT_STARTED
    if ((int)m_cur_phase < (int)INSERT)    { m_cur_phase = INSERT;    ... }  // was < SORT
    if ((int)m_cur_phase < (int)LOG_INDEX) { m_cur_phase = LOG_INDEX; ... }