• Marko Mäkelä's avatar
    MDEV-17899: Fix a regression from MDEV-17793 · 1b31d885
    Marko Mäkelä authored
    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.
    1b31d885
dict0mem.h 76.5 KB