summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksey Midenkov <midenok@gmail.com>2022-10-18 00:48:10 +0300
committerAleksey Midenkov <midenok@gmail.com>2022-10-18 00:49:06 +0300
commitb450eb4b385ceb572105e59efc07f72b44b220f0 (patch)
tree80e98229587bcfc58f6690ed1a057d27b3d91177
parent0d2b41f698e442640b0dcffed0305d3b8195ecc1 (diff)
downloadmariadb-git-bb-10.10-midenok-MDEV-27180.tar.gz
ddl_log_link_chains() improvedbb-10.10-midenok-MDEV-27180
ddl_log_link_chains() now can operate on empty master chain. If the master chain is empty it first writes empty execute entry to it. Usable when you need to link the chains before start filling the master chain. ddl_log_execute_recovery() now can skip empty execute entries.
-rw-r--r--sql/ddl_log.cc14
-rw-r--r--sql/ddl_log.h2
-rw-r--r--sql/sql_table.cc9
3 files changed, 21 insertions, 4 deletions
diff --git a/sql/ddl_log.cc b/sql/ddl_log.cc
index 60d28d0e6ec..37d8900e974 100644
--- a/sql/ddl_log.cc
+++ b/sql/ddl_log.cc
@@ -3800,8 +3800,20 @@ bool ddl_log_rename_frm(DDL_LOG_STATE *ddl_state,
CREATE OR REPLACE ... is used.
*/
-void ddl_log_link_chains(DDL_LOG_STATE *state, DDL_LOG_STATE *master_state)
+bool ddl_log_link_chains(DDL_LOG_STATE *state, DDL_LOG_STATE *master_state)
{
+ if (!master_state->execute_entry)
+ {
+ mysql_mutex_lock(&LOCK_gdl);
+ if (ddl_log_write_execute_entry(0, master_state->master_chain_pos,
+ &master_state->execute_entry))
+ {
+ mysql_mutex_unlock(&LOCK_gdl);
+ return true;
+ }
+ mysql_mutex_unlock(&LOCK_gdl);
+ }
DBUG_ASSERT(master_state->execute_entry);
state->master_chain_pos= master_state->execute_entry->entry_pos;
+ return false;
}
diff --git a/sql/ddl_log.h b/sql/ddl_log.h
index c166f1da06e..f0e05412824 100644
--- a/sql/ddl_log.h
+++ b/sql/ddl_log.h
@@ -369,6 +369,6 @@ bool ddl_log_store_query(THD *thd, DDL_LOG_STATE *ddl_log_state,
bool ddl_log_delete_frm(DDL_LOG_STATE *ddl_state, const char *to_path);
bool ddl_log_rename_frm(DDL_LOG_STATE *ddl_state,
const char *from_path, const char *to_path);
-void ddl_log_link_chains(DDL_LOG_STATE *state, DDL_LOG_STATE *master_state);
+bool ddl_log_link_chains(DDL_LOG_STATE *state, DDL_LOG_STATE *master_state);
extern mysql_mutex_t LOCK_gdl;
#endif /* DDL_LOG_INCLUDED */
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index ef1cfcd2171..c7ff17e229b 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -4399,10 +4399,15 @@ bool HA_CREATE_INFO::finalize_atomic_replace(THD *thd, TABLE_LIST *orig_table)
DBUG_ASSERT(is_atomic_replace());
debug_crash_here("ddl_log_create_before_install_new");
+ /* If old table exists, rename it to backup_name */
if (old_hton)
{
- /* Old table exists, rename it to backup_name */
- ddl_log_link_chains(ddl_log_state_rm, ddl_log_state_create);
+ /*
+ Cleanup chain (ddl_log_state_rm) will not be executed unless
+ rollback chain (ddl_log_state_create) is active.
+ */
+ if (ddl_log_link_chains(ddl_log_state_rm, ddl_log_state_create))
+ return true;
cpath.length= build_table_filename(path, sizeof(path) - 1,
backup_name.db.str,