MDEV-38140: InnoDB index corruption after UPDATE affecting virtual

columns

Issue:
- Purge thread attempts to purge a secondary index record that is not
  delete-marked.

Root Cause:
- When a secondary index includes a virtual column whose v_pos is
  greater than the number of fields in the clustered index record, the
  virtual column is incorrectly skipped while reading from the undo
  record.
- This leads the purge logic to incorrectly assume it is safe to purge
  the secondary index record.
- The code also confuses the nth virtual column with the nth stored
  column when writing ordering columns at the end of the undo record.

Fix:
- In trx_undo_update_rec_get_update(): Skip a virtual column only
  when v_pos == FIL_NULL, not when v_pos is greater than the number
  of fields.
- In trx_undo_page_report_modify(): Ensure ordering columns are
  written based on the correct stored-column positions, without
  confusing them with virtual-column positions.
This commit is contained in:
Mohammad Tafzeel Shams 2025-12-05 15:18:44 +05:30
commit 7fed014308
3 changed files with 89 additions and 3 deletions

View file

@ -1222,9 +1222,12 @@ store_len:
columns that were updated. */
for (i = 0; i < update->n_fields; i++) {
const upd_field_t* fld =
upd_get_nth_field(update, i);
if (upd_fld_is_virtual_col(fld))
continue;
const ulint field_no
= upd_get_nth_field(update, i)
->field_no;
= fld->field_no;
if (field_no >= index->n_fields
|| dict_index_get_nth_field(
index, field_no)->col
@ -1524,7 +1527,7 @@ trx_undo_update_rec_get_update(
&field_no);
first_v_col = false;
/* This column could be dropped or no longer indexed */
if (field_no >= index->n_fields) {
if (field_no == FIL_NULL) {
/* Mark this is no longer needed */
upd_field->field_no = REC_MAX_N_FIELDS;