Skip to content
  • Marko Mäkelä's avatar
    045f2c58
    Bug#15989081 INNODB ALTER TABLE IS NOT ATOMIC · 045f2c58
    Marko Mäkelä authored
    Revert the work-around and really fix
    Bug#14105491 ADD FOREIGN KEY ON COLUMNS BEING RENAMED DOES NOT WORK CORRECTLY
    
    Refactor ha_innobase::commit_inplace_alter_table() as follows:
    
    First, update the data dictionary definitions in the persistent data
    dictionary within a single data dictionary transaction. If any step
    fails, roll back the dictionary transaction. Update the foreign key
    constraints in the same data dictionary transaction with everything
    else.
    
    Only if the definitions were successfully updated, perform the
    corresponding modifications in the data dictionary cache. In this way,
    there is no need to implement any logic for rolling back any changes
    in the data dictionary cache. (Adding an index is the most notable
    exception to this, as we will allocate a placeholder for the index.)
    
    dict_foreign_eval_sql(): Replace dict_table_t and dict_foreign_t with
    table name and foreign key id.
    
    dict_create_add_foreign_field_to_dictionary(): Replace dict_table_t
    with table_name.
    
    dict_create_add_foreign_to_dictionary(): Replace dict_table_t with
    table name. Remove the parameter id_nr, and assume that foreign->id be
    assigned by the caller.
    
    dict_create_add_foreign_id(): Assign foreign->id if needed. This used
    to be part of dict_create_add_foreign_to_dictionary().
    
    dict_foreign_find_index(): dict_foreign_add_to_cache(),
    dict_foreign_qualify_index(), dict_load_foreign(),
    dict_load_foreigns(): Add the parameter col_names[], to be used
    instead of table->col_names when the columns are being renamed but the
    table definition in the data dictionary cache has not been updated
    yet.
    
    dict_foreign_replace_index(): Add the parameter col_names[] and remove
    the parameter trx. Return a Boolean, indicating whether all
    replacements were found.
    
    fil_mtr_rename_log(): Add the parameter mtr, so that multiple renames
    can be logged in a single mini-transaction, together with logging a
    transaction commit.
    
    innobase_check_fk_option(): Make the parameter const.
    
    innobase_find_fk_index(), innobase_get_foreign_key_info(): Add the
    parameter col_names[] so that this can work with renamed columns. Add
    the parameters drop_index[] and n_drop_index to avoid future conflicts
    with RENAME INDEX or other operations.
    
    ha_innobase_inplace_ctx: Add user_trx, col_names[] and tmp_name.
    
    innobase_get_col_names(): Initialize a list of all column names in the
    table if any columns were renamed. This will be used for initializing
    ctx->col_names.
    
    prepare_inplace_alter_table_dict(): Take most parameters via
    ha_alter_info->handler_ctx. When the table is rebuilt, the new copy of
    the table (ctx->indexed_table) will contain the renamed columns, so the
    ctx->col_names will be reset to NULL.
    
    innobase_check_foreign_key_index(): Add the parameter col_names[].
    
    innobase_drop_foreign_try(): Renamed from innobase_drop_foreign_dict().
    Replace TABLE_SHARE with table_name and dict_foreign_t with
    foreign_id. Do not touch the data dictionary cache.
    
    innobase_rename_column_try(): Renamed from innobase_rename_column().
    Replace TABLE_SHARE with table_name and prebuilt with user_table. Do
    not touch the data dictionary cache.
    
    innobase_rename_columns_try(): Renamed from innobase_rename_columns().
    Replace TABLE_SHARE with table_name and prebuilt with user_table.
    
    innobase_undo_add_fk(): Remove. No FOREIGN KEY operations will not be
    performed in the data dictionary cache until after the dictionary
    transaction has been committed.
    
    innobase_rename_columns_cache(): New function, for renaming the
    columns of a table in the data dictionary cache. This is only needed
    when the table was not rebuilt.
    
    commit_get_autoinc(): Refactored function, for getting the
    auto-increment value of the table on commit.
    
    innobase_update_foreign_try(): New function: Add or drop foreign key
    constraints.
    
    innobase_update_foreign_cache(): New function: Add or drop foreign key
    constraints in the data dictionary cache after the changes were
    committed. We will rely on dict_load_foreigns().
    
    commit_try_rebuild(): Refactored function: Apply the changes to the
    data dictionary tables when the table was rebuilt.
    
    commit_cache_rebuild(): New function: Apply the changes to the
    data dictionary cache and the file system after the changes were
    committed. The table will not be dropped here.
    
    commit_try_norebuild(): Refactored function: Apply the changes to the
    data dictionary tables when the table was not rebuilt.
    
    commit_cache_norebuild(): New function: Apply the changes to the data
    dictionary cache and the file system after the changes were
    committed. TODO: Do the actual DROP INDEX
    (row_merge_drop_indexes_dict) later, outside exclusive metadata lock.
    
    commit_update_stats(): Refactored function: Update index cardinality
    statistics after the ALTER TABLE operation was committed.
    
    ha_innobase::commit_inplace_alter_table(): Do not modify the data
    dictionary cache until after the data dictionary transaction has been
    committed.
    
    row_merge_rename_tables_dict(): Renamed from row_merge_rename_tables().
    Do not commit the transaction.
    
    trx_commit_low(): New function, to commit a transaction together with
    an already started mini-transaction. This will be called by
    ha_innobase::commit_inplace_alter_table() when rebuilding the table.
    
    rb#1637 approved by Jimmy Yang
    045f2c58
    Bug#15989081 INNODB ALTER TABLE IS NOT ATOMIC
    Marko Mäkelä authored
    Revert the work-around and really fix
    Bug#14105491 ADD FOREIGN KEY ON COLUMNS BEING RENAMED DOES NOT WORK CORRECTLY
    
    Refactor ha_innobase::commit_inplace_alter_table() as follows:
    
    First, update the data dictionary definitions in the persistent data
    dictionary within a single data dictionary transaction. If any step
    fails, roll back the dictionary transaction. Update the foreign key
    constraints in the same data dictionary transaction with everything
    else.
    
    Only if the definitions were successfully updated, perform the
    corresponding modifications in the data dictionary cache. In this way,
    there is no need to implement any logic for rolling back any changes
    in the data dictionary cache. (Adding an index is the most notable
    exception to this, as we will allocate a placeholder for the index.)
    
    dict_foreign_eval_sql(): Replace dict_table_t and dict_foreign_t with
    table name and foreign key id.
    
    dict_create_add_foreign_field_to_dictionary(): Replace dict_table_t
    with table_name.
    
    dict_create_add_foreign_to_dictionary(): Replace dict_table_t with
    table name. Remove the parameter id_nr, and assume that foreign->id be
    assigned by the caller.
    
    dict_create_add_foreign_id(): Assign foreign->id if needed. This used
    to be part of dict_create_add_foreign_to_dictionary().
    
    dict_foreign_find_index(): dict_foreign_add_to_cache(),
    dict_foreign_qualify_index(), dict_load_foreign(),
    dict_load_foreigns(): Add the parameter col_names[], to be used
    instead of table->col_names when the columns are being renamed but the
    table definition in the data dictionary cache has not been updated
    yet.
    
    dict_foreign_replace_index(): Add the parameter col_names[] and remove
    the parameter trx. Return a Boolean, indicating whether all
    replacements were found.
    
    fil_mtr_rename_log(): Add the parameter mtr, so that multiple renames
    can be logged in a single mini-transaction, together with logging a
    transaction commit.
    
    innobase_check_fk_option(): Make the parameter const.
    
    innobase_find_fk_index(), innobase_get_foreign_key_info(): Add the
    parameter col_names[] so that this can work with renamed columns. Add
    the parameters drop_index[] and n_drop_index to avoid future conflicts
    with RENAME INDEX or other operations.
    
    ha_innobase_inplace_ctx: Add user_trx, col_names[] and tmp_name.
    
    innobase_get_col_names(): Initialize a list of all column names in the
    table if any columns were renamed. This will be used for initializing
    ctx->col_names.
    
    prepare_inplace_alter_table_dict(): Take most parameters via
    ha_alter_info->handler_ctx. When the table is rebuilt, the new copy of
    the table (ctx->indexed_table) will contain the renamed columns, so the
    ctx->col_names will be reset to NULL.
    
    innobase_check_foreign_key_index(): Add the parameter col_names[].
    
    innobase_drop_foreign_try(): Renamed from innobase_drop_foreign_dict().
    Replace TABLE_SHARE with table_name and dict_foreign_t with
    foreign_id. Do not touch the data dictionary cache.
    
    innobase_rename_column_try(): Renamed from innobase_rename_column().
    Replace TABLE_SHARE with table_name and prebuilt with user_table. Do
    not touch the data dictionary cache.
    
    innobase_rename_columns_try(): Renamed from innobase_rename_columns().
    Replace TABLE_SHARE with table_name and prebuilt with user_table.
    
    innobase_undo_add_fk(): Remove. No FOREIGN KEY operations will not be
    performed in the data dictionary cache until after the dictionary
    transaction has been committed.
    
    innobase_rename_columns_cache(): New function, for renaming the
    columns of a table in the data dictionary cache. This is only needed
    when the table was not rebuilt.
    
    commit_get_autoinc(): Refactored function, for getting the
    auto-increment value of the table on commit.
    
    innobase_update_foreign_try(): New function: Add or drop foreign key
    constraints.
    
    innobase_update_foreign_cache(): New function: Add or drop foreign key
    constraints in the data dictionary cache after the changes were
    committed. We will rely on dict_load_foreigns().
    
    commit_try_rebuild(): Refactored function: Apply the changes to the
    data dictionary tables when the table was rebuilt.
    
    commit_cache_rebuild(): New function: Apply the changes to the
    data dictionary cache and the file system after the changes were
    committed. The table will not be dropped here.
    
    commit_try_norebuild(): Refactored function: Apply the changes to the
    data dictionary tables when the table was not rebuilt.
    
    commit_cache_norebuild(): New function: Apply the changes to the data
    dictionary cache and the file system after the changes were
    committed. TODO: Do the actual DROP INDEX
    (row_merge_drop_indexes_dict) later, outside exclusive metadata lock.
    
    commit_update_stats(): Refactored function: Update index cardinality
    statistics after the ALTER TABLE operation was committed.
    
    ha_innobase::commit_inplace_alter_table(): Do not modify the data
    dictionary cache until after the data dictionary transaction has been
    committed.
    
    row_merge_rename_tables_dict(): Renamed from row_merge_rename_tables().
    Do not commit the transaction.
    
    trx_commit_low(): New function, to commit a transaction together with
    an already started mini-transaction. This will be called by
    ha_innobase::commit_inplace_alter_table() when rebuilding the table.
    
    rb#1637 approved by Jimmy Yang
Loading