MDEV-17899: Fix a regression from MDEV-17793
The fix of MDEV-17793 was updating SYS_INDEXES.TABLE_ID in order to make the table invisible to purge (lazily delete old undo log records). By design of InnoDB, an update of TABLE_ID cannot be rolled back, because the rollback would effectively drop all indexes of the table due to the internal 'trigger' on SYS_INDEXES modifications. So, we revert the code change of MDEV-17793 and instead fix MDEV-17793 in a different way: by tweaking the undo log parsing during purge. The MDEV-17793 bug scenario is that a table becomes empty and a third instant ALTER TABLE is executed before purge processes the undo log record for the second instant ALTER TABLE. After this point, when purge sees the record, the table could have a mismatching number of rows. The test case works with this alternative fix. But what about a scenario where a fourth instant ALTER TABLE arrives before purge processes the second one? Could anything bad happen? Purge is only doing two things: First, free any BLOBs that were affected by the update record, and then, reset the DB_TRX_ID,DB_ROLL_PTR if a matching record is found. For the hidden metadata record, the only BLOB that we update is the hidden metadata BLOB that was introduced by MDEV-15562. Any other BLOBs (for the initial default values of instantly added columns) are never updated. So, in our scenario, the metadata BLOB that was created by the first instant ALTER TABLE (if it involved dropping or permuting columns) would be freed by purge when it is processing the undo record of the second ALTER TABLE. The BLOB value that was written by the second ALTER TABLE should be freed when the table is emptied. This is currently not done: MDEV-17383 should fix that. There is no possibility of double-free, because purge would only free old values of BLOBs. What about MVCC and other callers of trx_undo_update_rec_get_update()? The answer is simple: they should never be accessing the hidden metadata record in the first place. dict_table_t::reassign_id(): Remove. btr_cur_pessimistic_delete(): Clarify a comment. row_mysql_table_id_reassign(), row_discard_tablespace_for_mysql(): Add comments explaining that the operation cannot be rolled back. trx_undo_update_rec_get_update(): Avoid out-of-bounds access when parsing a metadata record. Avoid unnecessary memory allocation when filtering out fields from the update vector.
Showing
Please register or sign in to comment