diff options
author | Sergei Golubchik <sergii@pisem.net> | 2014-05-08 10:01:31 +0200 |
---|---|---|
committer | Sergei Golubchik <sergii@pisem.net> | 2014-05-08 10:01:31 +0200 |
commit | 9927b36e87652c6dc4ff2425e86570d678bac224 (patch) | |
tree | b576f9bd891a28e0cd64cc50c610d1340cbeff34 /sql/ha_partition.cc | |
parent | 8db4a5181532d7abbd4458aa127a1b192cc50f8c (diff) | |
download | mariadb-git-9927b36e87652c6dc4ff2425e86570d678bac224.tar.gz |
merge of "Bug#16216513 INPLACE ALTER DISABLED FOR PARTITIONED TABLES"
revno: 4777
committer: Marko Mäkelä <marko.makela@oracle.com>
branch nick: mysql-5.6
timestamp: Fri 2013-02-15 10:32:25 +0200
message:
Bug#16216513 INPLACE ALTER DISABLED FOR PARTITIONED TABLES
Diffstat (limited to 'sql/ha_partition.cc')
-rw-r--r-- | sql/ha_partition.cc | 177 |
1 files changed, 55 insertions, 122 deletions
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index e683fb91700..c1dbb6c5dd6 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -8145,7 +8145,6 @@ class ha_partition_inplace_ctx : public inplace_alter_handler_ctx { public: inplace_alter_handler_ctx **handler_ctx_array; - bool rollback_done; private: uint m_tot_parts; @@ -8153,7 +8152,6 @@ public: ha_partition_inplace_ctx(THD *thd, uint tot_parts) : inplace_alter_handler_ctx(), handler_ctx_array(NULL), - rollback_done(false), m_tot_parts(tot_parts) {} @@ -8172,14 +8170,11 @@ enum_alter_inplace_result ha_partition::check_if_supported_inplace_alter(TABLE *altered_table, Alter_inplace_info *ha_alter_info) { -#ifdef PARTITION_SUPPORTS_INPLACE_ALTER uint index= 0; enum_alter_inplace_result result= HA_ALTER_INPLACE_NO_LOCK; ha_partition_inplace_ctx *part_inplace_ctx; + bool first_is_set= false; THD *thd= ha_thd(); -#else - enum_alter_inplace_result result= HA_ALTER_INPLACE_NOT_SUPPORTED; -#endif DBUG_ENTER("ha_partition::check_if_supported_inplace_alter"); /* @@ -8190,32 +8185,18 @@ ha_partition::check_if_supported_inplace_alter(TABLE *altered_table, if (ha_alter_info->alter_info->flags == Alter_info::ALTER_PARTITION) DBUG_RETURN(HA_ALTER_INPLACE_NO_LOCK); -#ifndef PARTITION_SUPPORTS_INPLACE_ALTER - /* - Due to bug#14760210 partitions can be out-of-sync in case - commit_inplace_alter_table fails after the first partition. - - Until we can either commit all partitions at the same time or - have an atomic recover on failure/crash we don't support any - inplace alter. - - TODO: investigate what happens when indexes are out-of-sync - between partitions. If safe and possible to recover from, - then we could allow ADD/DROP INDEX. - */ - DBUG_RETURN(result); -#else part_inplace_ctx= new (thd->mem_root) ha_partition_inplace_ctx(thd, m_tot_parts); if (!part_inplace_ctx) DBUG_RETURN(HA_ALTER_ERROR); part_inplace_ctx->handler_ctx_array= (inplace_alter_handler_ctx **) - thd->alloc(sizeof(inplace_alter_handler_ctx *) * m_tot_parts); + thd->alloc(sizeof(inplace_alter_handler_ctx *) * (m_tot_parts + 1)); if (!part_inplace_ctx->handler_ctx_array) DBUG_RETURN(HA_ALTER_ERROR); - for (index= 0; index < m_tot_parts; index++) + /* Set all to NULL, including the terminating one. */ + for (index= 0; index <= m_tot_parts; index++) part_inplace_ctx->handler_ctx_array[index]= NULL; for (index= 0; index < m_tot_parts; index++) @@ -8225,15 +8206,32 @@ ha_partition::check_if_supported_inplace_alter(TABLE *altered_table, ha_alter_info); part_inplace_ctx->handler_ctx_array[index]= ha_alter_info->handler_ctx; + if (index == 0) + { + first_is_set= (ha_alter_info->handler_ctx != NULL); + } + else if (first_is_set != (ha_alter_info->handler_ctx != NULL)) + { + /* Either none or all partitions must set handler_ctx! */ + DBUG_ASSERT(0); + DBUG_RETURN(HA_ALTER_ERROR); + } if (p_result < result) result= p_result; if (result == HA_ALTER_ERROR) break; } + ha_alter_info->handler_ctx= part_inplace_ctx; + /* + To indicate for future inplace calls that there are several + partitions/handlers that need to be committed together, + we set group_commit_ctx to the NULL terminated array of + the partitions handlers. + */ + ha_alter_info->group_commit_ctx= part_inplace_ctx->handler_ctx_array; DBUG_RETURN(result); -#endif } @@ -8314,8 +8312,8 @@ bool ha_partition::commit_inplace_alter_table(TABLE *altered_table, Alter_inplace_info *ha_alter_info, bool commit) { - uint index= 0; ha_partition_inplace_ctx *part_inplace_ctx; + bool error= false; DBUG_ENTER("ha_partition::commit_inplace_alter_table"); @@ -8329,117 +8327,52 @@ bool ha_partition::commit_inplace_alter_table(TABLE *altered_table, part_inplace_ctx= static_cast<class ha_partition_inplace_ctx*>(ha_alter_info->handler_ctx); - if (!commit && part_inplace_ctx->rollback_done) - DBUG_RETURN(false); // We have already rolled back changes. - - for (index= 0; index < m_tot_parts; index++) + if (commit) { - ha_alter_info->handler_ctx= part_inplace_ctx->handler_ctx_array[index]; - if (m_file[index]->ha_commit_inplace_alter_table(altered_table, - ha_alter_info, commit)) + DBUG_ASSERT(ha_alter_info->group_commit_ctx == + part_inplace_ctx->handler_ctx_array); + ha_alter_info->handler_ctx= part_inplace_ctx->handler_ctx_array[0]; + error= m_file[0]->ha_commit_inplace_alter_table(altered_table, + ha_alter_info, commit); + if (error) + goto end; + if (ha_alter_info->group_commit_ctx) { - part_inplace_ctx->handler_ctx_array[index]= ha_alter_info->handler_ctx; - goto err; - } - part_inplace_ctx->handler_ctx_array[index]= ha_alter_info->handler_ctx; - DBUG_EXECUTE_IF("ha_partition_fail_final_add_index", { - /* Simulate failure by rollback of the second partition */ - if (m_tot_parts > 1) + /* + If ha_alter_info->group_commit_ctx is not set to NULL, + then the engine did only commit the first partition! + The engine is probably new, since both innodb and the default + implementation of handler::commit_inplace_alter_table sets it to NULL + and simply return false, since it allows metadata changes only. + Loop over all other partitions as to follow the protocol! + */ + uint i; + DBUG_ASSERT(0); + for (i= 1; i < m_tot_parts; i++) { - index++; - ha_alter_info->handler_ctx= part_inplace_ctx->handler_ctx_array[index]; - m_file[index]->ha_commit_inplace_alter_table(altered_table, - ha_alter_info, false); - part_inplace_ctx->handler_ctx_array[index]= ha_alter_info->handler_ctx; - goto err; + ha_alter_info->handler_ctx= part_inplace_ctx->handler_ctx_array[i]; + error|= m_file[i]->ha_commit_inplace_alter_table(altered_table, + ha_alter_info, + true); } - }); } - ha_alter_info->handler_ctx= part_inplace_ctx; - - DBUG_RETURN(false); - -err: - ha_alter_info->handler_ctx= part_inplace_ctx; - /* - Reverting committed changes is (for now) only possible for ADD INDEX - For other changes we will just try to rollback changes. - */ - if (index > 0 && - ha_alter_info->handler_flags & (Alter_inplace_info::ADD_INDEX | - Alter_inplace_info::ADD_UNIQUE_INDEX | - Alter_inplace_info::ADD_PK_INDEX)) - { - Alter_inplace_info drop_info(ha_alter_info->create_info, - ha_alter_info->alter_info, - NULL, 0, - ha_alter_info->modified_part_info, - ha_alter_info->ignore); - - if (ha_alter_info->handler_flags & Alter_inplace_info::ADD_INDEX) - drop_info.handler_flags|= Alter_inplace_info::DROP_INDEX; - if (ha_alter_info->handler_flags & Alter_inplace_info::ADD_UNIQUE_INDEX) - drop_info.handler_flags|= Alter_inplace_info::DROP_UNIQUE_INDEX; - if (ha_alter_info->handler_flags & Alter_inplace_info::ADD_PK_INDEX) - drop_info.handler_flags|= Alter_inplace_info::DROP_PK_INDEX; - drop_info.index_drop_count= ha_alter_info->index_add_count; - drop_info.index_drop_buffer= - (KEY**) ha_thd()->alloc(sizeof(KEY*) * drop_info.index_drop_count); - if (!drop_info.index_drop_buffer) - { - sql_print_error("Failed with error handling of adding index:\n" - "committing index failed, and when trying to revert " - "already committed partitions we failed allocating\n" - "memory for the index for table '%s'", - table_share->table_name.str); - DBUG_RETURN(true); - } - for (uint i= 0; i < drop_info.index_drop_count; i++) - drop_info.index_drop_buffer[i]= - &ha_alter_info->key_info_buffer[ha_alter_info->index_add_buffer[i]]; - - // Drop index for each partition where we already committed new index. - for (uint i= 0; i < index; i++) - { - bool error= m_file[i]->ha_prepare_inplace_alter_table(altered_table, - &drop_info); - error|= m_file[i]->ha_inplace_alter_table(altered_table, &drop_info); - error|= m_file[i]->ha_commit_inplace_alter_table(altered_table, - &drop_info, true); - if (error) - sql_print_error("Failed with error handling of adding index:\n" - "committing index failed, and when trying to revert " - "already committed partitions we failed removing\n" - "the index for table '%s' partition nr %d", - table_share->table_name.str, i); } - - // Rollback uncommitted changes. - for (uint i= index+1; i < m_tot_parts; i++) + else + { + uint i; + for (i= 0; i < m_tot_parts; i++) { + /* Rollback, commit == false, is done for each partition! */ ha_alter_info->handler_ctx= part_inplace_ctx->handler_ctx_array[i]; if (m_file[i]->ha_commit_inplace_alter_table(altered_table, ha_alter_info, false)) - { - /* How could this happen? */ - sql_print_error("Failed with error handling of adding index:\n" - "Rollback of add_index failed for table\n" - "'%s' partition nr %d", - table_share->table_name.str, i); + error= true; } - part_inplace_ctx->handler_ctx_array[i]= ha_alter_info->handler_ctx; } - - // We have now reverted/rolled back changes. Set flag to prevent - // it from being done again. - part_inplace_ctx->rollback_done= true; - - print_error(HA_ERR_NO_PARTITION_FOUND, MYF(0)); - } - +end: ha_alter_info->handler_ctx= part_inplace_ctx; - DBUG_RETURN(true); + DBUG_RETURN(error); } |