• Marko Mäkelä's avatar
    MDEV-13654 Various crashes due to DB_TRX_ID mismatch in table-rebuilding ALTER TABLE…LOCK=NONE · ff81faf6
    Marko Mäkelä authored
    After MDEV-12288 and MDEV-13536, the DB_TRX_ID of old clustered index
    records for which no history is available should be reset to 0.
    
    This caused crashes in online table-rebuilding ALTER, because the
    row_log_table_apply() is built on the assumption that the PRIMARY KEY
    together with DB_TRX_ID,DB_ROLL_PTR identifies the record.
    
    Both when copying the old table and when writing log about changes to
    the old table, we must map "old" DB_TRX_ID to 0. "old" here is simply
    "older than the trx_id of the ALTER TABLE transaction", because
    the MDL_EXCLUSIVE (and exclusive InnoDB table lock) in
    ha_innobase::prepare_inplace_alter_table() forces any transactions
    accessing the table to commit or rollback. So, we know that we can
    safely reset any DB_TRX_ID in the table that is older than the
    transaction ID of the ALTER TABLE, because the undo log history would be
    lost in a table-rebuilding ALTER.
    
    Note: After a table-rebuilding online ALTER TABLE, the rebuilt table
    may end up containing some nonzero DB_TRX_ID columns. The apply logic
    identifies the rows by the combination of PRIMARY KEY and DB_TRX_ID.
    These nonzero DB_TRX_ID would necessarily refer to concurrent DML
    operations that were started during ha_innobase::inplace_alter_table().
    
    row_log_allocate(): Add a parameter for the ALTER TABLE transaction.
    
    row_log_t::min_trx: The ALTER TABLE transaction ID.
    
    trx_id_check(): A debug function to check that DB_TRX_ID makes sense
    (is either 0 or bigger than the ALTER TABLE transaction ID).
    
    reset_trx_id[]: The reset DB_TRX_ID,DB_ROLL_PTR columns.
    
    row_log_table_delete(), row_log_table_get_pk(): Reset the
    DB_TRX_ID,DB_ROLL_PTR when they precede the ALTER TABLE transaction.
    
    row_log_table_apply_delete(), row_log_table_apply_update():
    Assert trx_id_check().
    
    row_merge_insert_index_tuples(): Remove the unused parameter trx_id.
    
    row_merge_read_clustered_index(): In a table-rebuilding ALTER,
    reset the DB_TRX_ID,DB_ROLL_PTR when they precede the ALTER TABLE
    transaction. Assert trx_id_check() on clustered index records that
    are being buffered.
    ff81faf6
row0merge.cc 143 KB