summaryrefslogtreecommitdiff
path: root/sql/sql_partition_admin.cc
diff options
context:
space:
mode:
authorAleksey Midenkov <midenok@gmail.com>2021-12-05 22:20:20 +0300
committerAleksey Midenkov <midenok@gmail.com>2022-06-16 01:39:01 +0300
commit312a5ecdc41b1a5771bdbb3015eb2a928f03b89c (patch)
tree8578831b23276edd8ba5f927820d53042f03e639 /sql/sql_partition_admin.cc
parent18df0f35ab696e2ffb2dcc8a1cdefcdfd2898276 (diff)
downloadmariadb-git-bb-10.7-midenok-MDEV-27180.tar.gz
MDEV-27180 Fully atomic partitioning DDL operationsbb-10.7-midenok-MDEV-27180
Atomic DDL for partitioning originally covers crash-safety but it does not recover fully from failures. F.ex. if error happened during the rename or drop of partitions the ALTER operation does not return the table to its original state. The patch solves the above problem similarly to MDEV-25292 (atomic CREATE OR REPLACE): new partitions are created as temporary, old partitions are backed up, everything is guarded by two DDL log chains: rollback and cleanup. Rollback chain contains the actions that bring back the original table. Cleanup chain deletes the backup files. The generic operation of alter partition is as follows: 1. Create new partitions as tmp partitions; 2. Fill TMP partitions with data; 3. Rename old and not needed partitions to backup partitions; 4. Rename tmp partitions to original partititions; 5. Do any required logging (mariabackup, binary); 6. If everything is ok, drop the backup partitions; 7. In the case any of pp.1-5 fails drop new partitions, rename back backup partitions. Each rename operation is executed right after the corresponding DDL logging. Originally they were done in different loops: write_log_changed_partitions(), mysql_change_partitions(), etc. The actual table operations were done in ha_partition handler: ha_change_partitions(), ha_drop_partitions(), ha_rename_partitions(). Now these calls are deprecated and removed. Instead the above deprecated interfaces the following classes now handle DDL logging and table operations: Alter_partition_logger Alter_partition_add Alter_partition_change Alter_partition_logger handles the basic operation, DDL logging and table renames. Alter_partition_add does the stuff for adding the partitions. Alter_partition_change combines Alter_partition_logger and Alter_partition_add for complex operations such as REORGANIZE. ha_partition::change_partitions() call was not fully removed. Stages 1-4 from that call was renamed to allocate_partitions() and that is used by Alter_partition_add for initializing file handler arrays (m_added_file, m_reorged_file). ha_partition::prepare_new_partition() is renamed to create_partition() because it actually does ha_create() and the new name better describes what it does. DDL_LOG_DELETE/DDL_LOG_RENAME/DDL_LOG_REPLACE are now pure file operations. To process both .par and .frm files we now issue two actions instead of one. That makes interface more simple and that will be used by MDEV-16417 in future. All the table operations are done via other actions, such as DDL_LOG_RENAME_TABLE, DDL_LOG_DROP_TABLE, etc. DDL_LOG_RENAME_TABLE has new alter_partition option. With this option it does simple ha_rename_table() which is needed for renaming the partitions. The action for renaming the partitions must start from phase DDL_RENAME_PHASE_TABLE. The testing was refactored a bit. Many new fail/crash points was added, the test was powered by binary and mariabackup logging, it tests more ALTER commands with variations of partitions-only and subpartitions, without and under LOCK TABLES. EXCHANGE PARTITION was fixed: after failure under LOCK TABLES the table became unlocked. Fixed by correcting place of reopen_tables(). Tested by partition_debug.
Diffstat (limited to 'sql/sql_partition_admin.cc')
-rw-r--r--sql/sql_partition_admin.cc61
1 files changed, 3 insertions, 58 deletions
diff --git a/sql/sql_partition_admin.cc b/sql/sql_partition_admin.cc
index 134a01e4e0e..09dd0c5689b 100644
--- a/sql/sql_partition_admin.cc
+++ b/sql/sql_partition_admin.cc
@@ -396,7 +396,7 @@ static bool exchange_name_with_ddl_log(THD *thd,
*/
/* call rename table from table to tmp-name */
DBUG_EXECUTE_IF("exchange_partition_fail_3",
- my_error(ER_ERROR_ON_RENAME, MYF(0), name, tmp_name, 0);
+ my_error(ER_ERROR_ON_RENAME, MYF(0), name, "#TMP", 0);
error_set= TRUE;
goto err_rename;);
DBUG_EXECUTE_IF("exchange_partition_abort_3", DBUG_SUICIDE(););
@@ -430,7 +430,7 @@ static bool exchange_name_with_ddl_log(THD *thd,
/* call rename table from tmp-nam to partition */
DBUG_EXECUTE_IF("exchange_partition_fail_7",
- my_error(ER_ERROR_ON_RENAME, MYF(0), tmp_name, from_name, 0);
+ my_error(ER_ERROR_ON_RENAME, MYF(0), "#TMP", from_name, 0);
error_set= TRUE;
goto err_rename;);
DBUG_EXECUTE_IF("exchange_partition_abort_7", DBUG_SUICIDE(););
@@ -719,13 +719,6 @@ bool Sql_cmd_alter_table_exchange_partition::
temp_file_name, table_hton)))
goto err;
- /*
- Reopen tables under LOCK TABLES. Ignore the return value for now. It's
- better to keep master/slave in consistent state. Alternative would be to
- try to revert the exchange operation and issue error.
- */
- (void) thd->locked_tables_list.reopen_tables(thd, false);
-
if (force_if_exists)
thd->variables.option_bits|= OPTION_IF_EXISTS;
@@ -753,6 +746,7 @@ bool Sql_cmd_alter_table_exchange_partition::
err:
if (thd->locked_tables_mode)
{
+ (void) thd->locked_tables_list.reopen_tables(thd, false);
if (swap_table_mdl_ticket)
swap_table_mdl_ticket->downgrade_lock(MDL_SHARED_NO_READ_WRITE);
if (part_table_mdl_ticket)
@@ -999,53 +993,4 @@ bool Sql_cmd_alter_table_truncate_partition::execute(THD *thd)
DBUG_RETURN(error);
}
-
-/**
- Move a table specified in the CONVERT TABLE <table_name> TO PARTITION ...
- to the new partition.
-
- @param lpt A structure containing parameters regarding to the statement
- ALTER TABLE ... TO PARTITION ...
- @param part_file_name a file name of the partition being added
-
- @return false on success, true on error
-*/
-
-bool alter_partition_convert_in(ALTER_PARTITION_PARAM_TYPE *lpt)
-{
- char part_file_name[2*FN_REFLEN+1];
- THD *thd= lpt->thd;
- const char *path= lpt->table_list->table->s->path.str;
- TABLE_LIST *table_from= lpt->table_list->next_local;
-
- const char *partition_name=
- thd->lex->part_info->curr_part_elem->partition_name;
-
- if (create_partition_name(part_file_name, sizeof(part_file_name), path,
- partition_name, NORMAL_PART_NAME, false))
- return true;
-
- char from_file_name[FN_REFLEN+1];
-
- build_table_filename(from_file_name, sizeof(from_file_name),
- table_from->db.str, table_from->table_name.str, "", 0);
-
- handler *file= get_new_handler(nullptr, thd->mem_root,
- table_from->table->file->ht);
- if (unlikely(!file))
- return true;
-
- close_all_tables_for_name(thd, table_from->table->s,
- HA_EXTRA_PREPARE_FOR_RENAME, nullptr);
-
- bool res= file->ha_rename_table(from_file_name, part_file_name);
-
- if (res)
- my_error(ER_ERROR_ON_RENAME, MYF(0), from_file_name,
- part_file_name, my_errno);
-
- delete file;
- return res;
-}
-
#endif /* WITH_PARTITION_STORAGE_ENGINE */