diff options
Diffstat (limited to 'sql')
-rw-r--r-- | sql/datadict.cc | 58 | ||||
-rw-r--r-- | sql/handler.cc | 3 | ||||
-rw-r--r-- | sql/sql_class.h | 3 | ||||
-rw-r--r-- | sql/sql_rename.cc | 12 | ||||
-rw-r--r-- | sql/sql_table.cc | 34 |
5 files changed, 75 insertions, 35 deletions
diff --git a/sql/datadict.cc b/sql/datadict.cc index 07f67d25fd0..9369371f559 100644 --- a/sql/datadict.cc +++ b/sql/datadict.cc @@ -520,6 +520,7 @@ int FK_backup::fk_write_shadow_frm(ddl_log_info &log_info) { char shadow_path[FN_REFLEN + 1]; char frm_name[FN_REFLEN + 1]; + int err; TABLE_SHARE *s= get_share(); DBUG_ASSERT(s); build_table_shadow_filename(shadow_path, sizeof(shadow_path) - 1, @@ -528,9 +529,30 @@ int FK_backup::fk_write_shadow_frm(ddl_log_info &log_info) if (log_info.write_log_replace_delete_file(NULL, frm_name, false)) return true; delete_shadow_entry= log_info.first_entry; - int err= s->fk_write_shadow_frm_impl(shadow_path); - if (ERROR_INJECT("fail_fk_write_shadow", "crash_fk_write_shadow")) - return true; +#ifndef DBUG_OFF + if (log_info.dbg_fail && + (ERROR_INJECT("fail_fk_write_shadow_frm", "crash_fk_write_shadow_frm"))) + { + err= 10; + goto write_shadow_failed; + } +#endif + err= s->fk_write_shadow_frm_impl(shadow_path); + if (err) + { +#ifndef DBUG_OFF +write_shadow_failed: +#endif + if (deactivate_ddl_log_entry(delete_shadow_entry->entry_pos)) + { + /* This is very bad case because log replay will delete original frm. + At least try prohibit replaying it and push an alert message. */ + log_info.write_log_finish(); + my_printf_error(ER_DDL_LOG_ERROR, "Deactivating delete shadow entry %u failed", + MYF(0), delete_shadow_entry->entry_pos); + } + delete_shadow_entry= NULL; + } return err; } @@ -644,7 +666,35 @@ void FK_backup::fk_drop_backup_frm(ddl_log_info &log_info) } -bool FK_ddl_vector::install_shadow_frms(THD *thd) +int FK_ddl_vector::write_shadow_frms() +{ + int err; +#ifndef DBUG_OFF + FK_backup *last; + for (auto &bak: *this) + { + if (!bak.second.update_frm) + continue; + last= &bak.second; + } + dbg_fail= false; +#endif + for (auto &bak: *this) + { + if (!bak.second.update_frm) + continue; +#ifndef DBUG_OFF + if (&bak.second == last) + dbg_fail= true; +#endif + if ((err= bak.second.fk_write_shadow_frm(*this))) + return err; + } + return 0; +} + + +bool FK_ddl_vector::install_shadow_frms() { if (!size()) return false; diff --git a/sql/handler.cc b/sql/handler.cc index 1a35251871d..6555b992fd5 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -5541,7 +5541,8 @@ int ha_create_table(THD *thd, const char *path, if (fk_update_refs && (share.fk_handle_create(thd, fk_shares) || - fk_shares.install_shadow_frms(thd))) + fk_shares.write_shadow_frms() || + fk_shares.install_shadow_frms())) goto err; share.m_psi= PSI_CALL_get_table_share(temp_table, &share); diff --git a/sql/sql_class.h b/sql/sql_class.h index 913413e80a8..b98f13700f5 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1068,7 +1068,8 @@ public: class FK_ddl_vector: public mbd::map<TABLE_SHARE *, FK_ddl_backup>, public ddl_log_info { public: - bool install_shadow_frms(THD *thd); + int write_shadow_frms(); + bool install_shadow_frms(); void drop_backup_frms(THD *thd); void rollback(THD *thd); }; diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc index 3664ccd217a..184c00fad62 100644 --- a/sql/sql_rename.cc +++ b/sql/sql_rename.cc @@ -162,17 +162,9 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent, error= true; else { - for (auto &ref: fk_rename_backup) - { - if (ref.second.fk_write_shadow_frm(fk_rename_backup)) - { - error= true; - break; - } - } - + error= fk_rename_backup.write_shadow_frms(); if (!error) - error= fk_rename_backup.install_shadow_frms(thd); + error= fk_rename_backup.install_shadow_frms(); } /* An exclusive lock on table names is satisfactory to ensure diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 9587c09bd35..77c2e1dd968 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -2547,7 +2547,7 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, table_name.str, MDL_EXCLUSIVE)); - error= shares.install_shadow_frms(thd); + error= shares.install_shadow_frms(); if (unlikely(error)) { shares.rollback(thd); @@ -8277,7 +8277,7 @@ static bool mysql_inplace_alter_table(THD *thd, table_list->table= table= NULL; // FIXME: do right after fk_handle_alter? - if (alter_ctx->fk_ref_backup.install_shadow_frms(thd)) + if (alter_ctx->fk_ref_backup.install_shadow_frms()) { alter_ctx->fk_ref_backup.rollback(thd); DBUG_RETURN(true); @@ -10007,19 +10007,17 @@ simple_rename_or_index_change(THD *thd, TABLE_LIST *table_list, &alter_ctx->new_name, fk_rename_backup)) DBUG_RETURN(true); - for (auto &ref: fk_rename_backup) + + if (fk_rename_backup.write_shadow_frms()) { - if (ref.second.fk_write_shadow_frm(fk_rename_backup)) - { - fk_rename_backup.rollback(thd); - DBUG_RETURN(true); - } + fk_rename_backup.rollback(thd); + DBUG_RETURN(true); } close_all_tables_for_name(thd, table->s, HA_EXTRA_PREPARE_FOR_RENAME, NULL); - if (fk_rename_backup.install_shadow_frms(thd)) + if (fk_rename_backup.install_shadow_frms()) { fk_rename_backup.rollback(thd); DBUG_RETURN(true); @@ -11347,7 +11345,7 @@ err_rename_back: } } - if (alter_ctx.fk_ref_backup.install_shadow_frms(thd)) + if (alter_ctx.fk_ref_backup.install_shadow_frms()) goto err_rename_back; if (alter_ctx.is_table_renamed()) @@ -12574,9 +12572,6 @@ bool TABLE_SHARE::fk_handle_create(THD *thd, FK_ddl_vector &shares, FK_list *fk_ return true; } } // for (const FK_info &fk: fkeys) - - if (ref.second.fk_write_shadow_frm(shares)) - return true; } // for (ref_tables) return false; @@ -12980,12 +12975,8 @@ bool Alter_table_ctx::fk_handle_alter(THD *thd) } // for (const Table_name &ref: rk_renamed_table) /* Update EXTRA2_FOREIGN_KEY_INFO section in FRM files. */ - for (auto &key_val: fk_ref_backup) - { - FK_share_backup *ref_bak= &key_val.second; - if (ref_bak->update_frm && ref_bak->fk_write_shadow_frm(fk_ref_backup)) - return true; - } + if (fk_ref_backup.write_shadow_frms()) + return true; if (ERROR_INJECT("fail_fk_alter_3", "crash_fk_alter_3")) return true; @@ -13144,6 +13135,11 @@ bool fk_handle_drop(THD *thd, TABLE_LIST *table, FK_ddl_vector &shares, ref_it.remove(); } } + +#ifndef DBUG_OFF + shares.dbg_fail= true; +#endif + int err= ref->second.fk_write_shadow_frm(shares); if (err) { |