summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThirunarayanan Balathandayuthapani <thiru@mariadb.com>2020-03-27 16:32:52 +0530
committerThirunarayanan Balathandayuthapani <thiru@mariadb.com>2020-03-27 17:42:17 +0530
commit40977cd56ff1f7c68e7f7e481d3eddb98b21e1d6 (patch)
tree77c996b1501f3820978b4ee5b0bed05481ed62c7
parentba679ae52f0e9d698c1b36d28a5bc8c233e57a2e (diff)
downloadmariadb-git-bb-10.4-MDEV-21832.tar.gz
MDEV-21832 FORCE all partition to rebuild if any one of thebb-10.4-MDEV-21832
partition does rebuild - In ha_innobase::commit_inplace_alter_table() assumes that all partition should do the same kind of alter operations. During DDL, if one partition requires table rebuild and other partition doesn't need rebuild then all partition should be forced to rebuild.
-rw-r--r--mysql-test/suite/parts/r/partition_alter_instant.result34
-rw-r--r--mysql-test/suite/parts/t/partition_alter_instant.test43
-rw-r--r--sql/ha_partition.cc53
-rw-r--r--storage/innobase/handler/handler0alter.cc1
4 files changed, 106 insertions, 25 deletions
diff --git a/mysql-test/suite/parts/r/partition_alter_instant.result b/mysql-test/suite/parts/r/partition_alter_instant.result
new file mode 100644
index 00000000000..e5ef57db992
--- /dev/null
+++ b/mysql-test/suite/parts/r/partition_alter_instant.result
@@ -0,0 +1,34 @@
+CREATE TABLE t1 (
+id INT NOT NULL,
+name VARCHAR(30))ENGINE=InnoDB ROW_FORMAT=COMPACT CHARACTER SET=latin1
+PARTITION BY RANGE (id) (
+PARTITION p0 VALUES LESS THAN (50),
+PARTITION p1 VALUES LESS THAN (MAXVALUE)
+);
+INSERT INTO t1(id, name) VALUES(16, 'Me'), (337, 'ROFL');
+# Add and drop 31 Instant columns
+CREATE TABLE t2 LIKE t1;
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `id` int(11) NOT NULL,
+ `name` varchar(30) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=COMPACT
+ PARTITION BY RANGE (`id`)
+(PARTITION `p0` VALUES LESS THAN (50) ENGINE = InnoDB,
+ PARTITION `p1` VALUES LESS THAN MAXVALUE ENGINE = InnoDB)
+ALTER TABLE t2 REMOVE PARTITIONING;
+ALTER TABLE t1 EXCHANGE PARTITION p0 WITH TABLE t2;
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `id` int(11) NOT NULL,
+ `name` varchar(30) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=COMPACT
+SET ALTER_ALGORITHM=INSTANT;
+ALTER TABLE t1 ADD COLUMN col1 VARCHAR(255) NOT NULL DEFAULT repeat('a', 255);
+ERROR 0A000: ALGORITHM=INSTANT is not supported for this operation. Try ALGORITHM=INPLACE
+SET ALTER_ALGORITHM=INPLACE;
+ALTER TABLE t1 ADD COLUMN col1 VARCHAR(255) NOT NULL DEFAULT repeat('a', 255);
+DROP TABLE t1, t2;
+SET ALTER_ALGORITHM=DEFAULT;
diff --git a/mysql-test/suite/parts/t/partition_alter_instant.test b/mysql-test/suite/parts/t/partition_alter_instant.test
new file mode 100644
index 00000000000..3d798791517
--- /dev/null
+++ b/mysql-test/suite/parts/t/partition_alter_instant.test
@@ -0,0 +1,43 @@
+--source include/have_partition.inc
+--source include/have_innodb.inc
+--source include/have_innodb_16k.inc
+
+# MDEV-21832 FORCE all partition to rebuild if any one of the
+# partition does rebuild
+CREATE TABLE t1 (
+ id INT NOT NULL,
+ name VARCHAR(30))ENGINE=InnoDB ROW_FORMAT=COMPACT CHARACTER SET=latin1
+ PARTITION BY RANGE (id) (
+ PARTITION p0 VALUES LESS THAN (50),
+ PARTITION p1 VALUES LESS THAN (MAXVALUE)
+);
+
+INSERT INTO t1(id, name) VALUES(16, 'Me'), (337, 'ROFL');
+
+--echo # Add and drop 31 Instant columns
+--disable_query_log
+let $i = 1;
+while ($i < 32) {
+--eval ALTER TABLE t1 ADD COLUMN col$i VARCHAR(255) NOT NULL DEFAULT repeat('a', 255);
+inc $i;
+}
+
+let $i = 31;
+while ($i > 0) {
+--eval ALTER TABLE t1 DROP COLUMN col$i
+dec $i;
+}
+--enable_query_log
+
+CREATE TABLE t2 LIKE t1;
+SHOW CREATE TABLE t2;
+ALTER TABLE t2 REMOVE PARTITIONING;
+ALTER TABLE t1 EXCHANGE PARTITION p0 WITH TABLE t2;
+SHOW CREATE TABLE t2;
+SET ALTER_ALGORITHM=INSTANT;
+--error ER_ALTER_OPERATION_NOT_SUPPORTED
+ALTER TABLE t1 ADD COLUMN col1 VARCHAR(255) NOT NULL DEFAULT repeat('a', 255);
+SET ALTER_ALGORITHM=INPLACE;
+ALTER TABLE t1 ADD COLUMN col1 VARCHAR(255) NOT NULL DEFAULT repeat('a', 255);
+DROP TABLE t1, t2;
+SET ALTER_ALGORITHM=DEFAULT;
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index d65a4963905..e8a62438e02 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -10071,7 +10071,8 @@ ha_partition::check_if_supported_inplace_alter(TABLE *altered_table,
Alter_inplace_info *ha_alter_info)
{
uint index= 0;
- enum_alter_inplace_result result= HA_ALTER_INPLACE_NO_LOCK;
+ enum_alter_inplace_result result;
+ alter_table_operations orig_ops;
ha_partition_inplace_ctx *part_inplace_ctx;
bool first_is_set= false;
THD *thd= ha_thd();
@@ -10098,33 +10099,35 @@ ha_partition::check_if_supported_inplace_alter(TABLE *altered_table,
if (!part_inplace_ctx->handler_ctx_array)
DBUG_RETURN(HA_ALTER_ERROR);
- /* Set all to NULL, including the terminating one. */
- for (index= 0; index <= m_tot_parts; index++)
- part_inplace_ctx->handler_ctx_array[index]= NULL;
+ do {
+ result= HA_ALTER_INPLACE_NO_LOCK;
+ /* Set all to NULL, including the terminating one. */
+ for (index= 0; index <= m_tot_parts; index++)
+ part_inplace_ctx->handler_ctx_array[index]= NULL;
- ha_alter_info->handler_flags |= ALTER_PARTITIONED;
- for (index= 0; index < m_tot_parts; index++)
- {
- enum_alter_inplace_result p_result=
- m_file[index]->check_if_supported_inplace_alter(altered_table,
- ha_alter_info);
- part_inplace_ctx->handler_ctx_array[index]= ha_alter_info->handler_ctx;
-
- if (index == 0)
+ ha_alter_info->handler_flags |= ALTER_PARTITIONED;
+ orig_ops= ha_alter_info->handler_flags;
+ for (index= 0; index < m_tot_parts; index++)
{
- 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);
+ enum_alter_inplace_result p_result=
+ m_file[index]->check_if_supported_inplace_alter(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;
}
- if (p_result < result)
- result= p_result;
- if (result == HA_ALTER_ERROR)
- break;
- }
+ } while (orig_ops != ha_alter_info->handler_flags);
ha_alter_info->handler_ctx= part_inplace_ctx;
/*
diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc
index 4200e87fa7f..0f1d519b42b 100644
--- a/storage/innobase/handler/handler0alter.cc
+++ b/storage/innobase/handler/handler0alter.cc
@@ -2488,6 +2488,7 @@ cannot_create_many_fulltext_index:
}
if (need_rebuild || fts_need_rebuild) {
+ ha_alter_info->handler_flags |= ALTER_RECREATE_TABLE;
DBUG_RETURN(online
? HA_ALTER_INPLACE_COPY_NO_LOCK
: HA_ALTER_INPLACE_COPY_LOCK);