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
Open
MDEV-39081 InnoDB: tried to purge non-delete-marked record, assertion fails in row_purge_del_mark_error#4858Thirunarayanan wants to merge 1 commit into11.4from
Thirunarayanan wants to merge 1 commit into11.4from
Conversation
dr-m
reviewed
Mar 26, 2026
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) |
Contributor
There was a problem hiding this comment.
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
e082315 to
389210a
Compare
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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.