Skip to content
/ server Public

MDEV-39081 InnoDB: tried to purge non-delete-marked record, assertion fails in row_purge_del_mark_error#4858

Open
Thirunarayanan wants to merge 1 commit into11.4from
MDEV-39081
Open

MDEV-39081 InnoDB: tried to purge non-delete-marked record, assertion fails in row_purge_del_mark_error#4858
Thirunarayanan wants to merge 1 commit into11.4from
MDEV-39081

Conversation

@Thirunarayanan
Copy link
Copy Markdown
Member

Reason:

Following the changes in MDEV-38734, the server no longer marks all indexed virtual columns during an UPDATE operation. Consequently, ha_innobase::update() populates the upd_t vector with old_vrow but omits the actual data for these virtual columns.

Despite this omission, trx_undo_page_report_modify() continues to write metadata for indexed virtual columns into the undo log. Because the actual values are missing from the update vector, the undo log entry is recorded without the historical data for these columns.

When the purge thread processes the undo log to reconstruct a previous record state for MVCC, it identifies an indexed virtual column but finds no associated data.

The purge thread incorrectly interprets this missing data as a NULL value, rather than a "missing/unrecorded" value. The historical record is reconstructed with an incorrect NULL for the virtual column. This causes the purge thread to incorrectly identify and purge records that are not actually delete-marked, leading to abort of server.

Solution:

ha_innobase::column_bitmaps_signal(): Revert the column-marking logic to the state prior to commit a4e4a56, ensuring all indexed virtual columns are unconditionally marked during an UPDATE.

  • The previous "optimization" attempted to manually detect indexed column changes before marking virtual columns. The manual check for indexed column modifications is redundant. InnoDB already provides the UPD_NODE_NO_ORD_CHANGE flag within row_upd_step(). This flag is being used in trx_undo_page_report_modify() and trx_undo_read_undo_rec() should log or read virtual column values.

  • For INSERT and DELETE (outside of Online DDL contexts), the function now exits early. Since the MySQL server layer manages virtual column computation in TABLE::mark_virtual_columns_for_write() for inserts, handler-level re-marking provided no value.

Comment on lines -5061 to -5079
bool is_online_log= clust_index->online_log;

/*
Check if the clustered index is being updated.
If so, it is necessary to compute virtual columns that are part of
secondary indexes, to be able to re-compute those indexes.
*/
bool upd_pk= false;
for (uint j= 0; j < clust_index->n_user_defined_cols; ++j)
{
dict_col_t *col= clust_index->fields[j].col;
if (bitmap_is_set(table->write_set, static_cast<uint>(col->ind)))
{
upd_pk= 1;
break;
}
}

if (!is_online_log && !upd_pk)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The commit message and the description do not clearly say why this was reverted, or what was mentioned by the following comment in a4e4a56:

Also fix an assertion when InnoDB goes to update secondary indexes: If any part of the primary key is being updated, then add all virtual columns that are part of secondary indexes to the read_set.

… fails in row_purge_del_mark_error

Reason:
=======
Following the changes in MDEV-38734, the server no longer marks
all indexed virtual columns during an UPDATE operation.
Consequently, ha_innobase::update() populates the upd_t vector
with old_vrow but omits the actual data for these virtual columns.

Despite this omission, trx_undo_page_report_modify() continues to
write metadata for indexed virtual columns into the undo log. Because
the actual values are missing from the update vector, the undo log
entry is recorded without the historical data for these columns.

When the purge thread processes the undo log to reconstruct a
previous record state for MVCC, it identifies an indexed virtual
column but finds no associated data.

The purge thread incorrectly interprets this missing data as a NULL
value, rather than a "missing/unrecorded" value. The historical
record is reconstructed with an incorrect NULL for the virtual column.
This causes the purge thread to incorrectly identify and purge
records that are not actually delete-marked, leading to abort
of server.

Solution:
=========
ha_innobase::column_bitmaps_signal(): Revert the column-marking
logic to the state prior to commit a4e4a56, ensuring all
indexed virtual columns are unconditionally marked during an UPDATE.

The previous "optimization" attempted to manually detect indexed
column changes before marking virtual columns. The manual check
for indexed column modifications is redundant. InnoDB already
provides the UPD_NODE_NO_ORD_CHANGE flag within row_upd_step().
This flag is being used in trx_undo_page_report_modify() and
trx_undo_read_undo_rec() should log or read virtual column values.

Refactored column_bitmaps_signal() to accept a mark_for_update
parameter that controls when indexed virtual columns are marked.
TABLE::mark_columns_needed_for_update() is the only place that needs
mark_for_update=true because only UPDATE operations need to mark
indexed virtual columns for InnoDB's undo logging mechanism.

INSERT operation is already handled by
TABLE::mark_virtual_columns_for_write(insert_fl=true).
Even the commit a4e4a56 changes are
going to affect TABLE::mark_virtual_column_for_write(false) and
It is called during UPDATE operation, and that's when
column_bitmaps_signal() needs to mark  indexed virtual columns.

Online DDL has separate code path which is handled by
row_log_mark_virtual_cols() for all DML operations
@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.

@Thirunarayanan Thirunarayanan requested a review from dr-m March 27, 2026 15:04
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.

3 participants