From 1cd31bc13248bef52f7b62a37c394bd302488b15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 25 Apr 2019 14:04:44 +0300 Subject: [PATCH] Bug#28573894 ALTER PARTITIONED TABLE ADD AUTO_INCREMENT DIFF RESULT DEPENDING ON ALGORITHM For partitioned table, ensure that the AUTO_INCREMENT values will be assigned from the same sequence. This is based on the following change in MySQL 5.6.44: commit aaba359c13d9200747a609730dafafc3b63cd4d6 Author: Rahul Malik Date: Mon Feb 4 13:31:41 2019 +0530 Bug#28573894 ALTER PARTITIONED TABLE ADD AUTO_INCREMENT DIFF RESULT DEPENDING ON ALGORITHM Problem: When a partition table is in-place altered to add an auto-increment column, then its values are starting over for each partition. Analysis: In the case of in-place alter, InnoDB is creating a new sequence object for each partition. It is default initialized. So auto-increment columns start over for each partition. Fix: Assign old sequence of the partition to the sequence of next partition so it won't start over. RB#21148 Reviewed by Bin Su --- mysql-test/r/partition_innodb.result | 42 +++++++++++++++++++++++ mysql-test/t/partition_innodb.test | 24 +++++++++++++ sql/ha_partition.cc | 11 ++++-- sql/handler.h | 5 +-- storage/innobase/handler/handler0alter.cc | 19 +++++++++- storage/xtradb/handler/handler0alter.cc | 19 +++++++++- 6 files changed, 113 insertions(+), 7 deletions(-) diff --git a/mysql-test/r/partition_innodb.result b/mysql-test/r/partition_innodb.result index c00a75fed90..5deab4d84fc 100644 --- a/mysql-test/r/partition_innodb.result +++ b/mysql-test/r/partition_innodb.result @@ -918,3 +918,45 @@ ERROR HY000: CHECK OPTION failed 'test.v' SET GLOBAL innodb_stats_persistent= @save_isp; DROP view v; DROP TABLE t; +# +# Bug#28573894 ALTER PARTITIONED TABLE ADD AUTO_INCREMENT DIFF RESULT +# +CREATE TABLE t (a VARCHAR(10) NOT NULL,b INT,PRIMARY KEY (b)) ENGINE=INNODB +PARTITION BY RANGE (b) +(PARTITION pa VALUES LESS THAN (2), +PARTITION pb VALUES LESS THAN (20), +PARTITION pc VALUES LESS THAN (30), +PARTITION pd VALUES LESS THAN (40)); +INSERT INTO t +VALUES('A',0),('B',1),('C',2),('D',3),('E',4),('F',5),('G',25),('H',35); +CREATE TABLE t_copy LIKE t; +INSERT INTO t_copy SELECT * FROM t; +ALTER TABLE t ADD COLUMN r INT UNSIGNED NOT NULL AUTO_INCREMENT, +ADD UNIQUE KEY (r,b); +affected rows: 0 +info: Records: 0 Duplicates: 0 Warnings: 0 +ALTER TABLE t_copy ADD COLUMN r INT UNSIGNED NOT NULL AUTO_INCREMENT, +ADD UNIQUE KEY (r,b), ALGORITHM=COPY; +affected rows: 8 +info: Records: 8 Duplicates: 0 Warnings: 0 +SELECT * FROM t; +a b r +A 0 1 +B 1 2 +C 2 3 +D 3 4 +E 4 5 +F 5 6 +G 25 7 +H 35 8 +SELECT * FROM t_copy; +a b r +A 0 1 +B 1 2 +C 2 3 +D 3 4 +E 4 5 +F 5 6 +G 25 7 +H 35 8 +DROP TABLE t,t_copy; diff --git a/mysql-test/t/partition_innodb.test b/mysql-test/t/partition_innodb.test index 54994bc5a66..15c9625770b 100644 --- a/mysql-test/t/partition_innodb.test +++ b/mysql-test/t/partition_innodb.test @@ -1028,3 +1028,27 @@ SET GLOBAL innodb_stats_persistent= @save_isp; DROP view v; DROP TABLE t; +--echo # +--echo # Bug#28573894 ALTER PARTITIONED TABLE ADD AUTO_INCREMENT DIFF RESULT +--echo # +CREATE TABLE t (a VARCHAR(10) NOT NULL,b INT,PRIMARY KEY (b)) ENGINE=INNODB +PARTITION BY RANGE (b) +(PARTITION pa VALUES LESS THAN (2), + PARTITION pb VALUES LESS THAN (20), + PARTITION pc VALUES LESS THAN (30), + PARTITION pd VALUES LESS THAN (40)); + +INSERT INTO t +VALUES('A',0),('B',1),('C',2),('D',3),('E',4),('F',5),('G',25),('H',35); +CREATE TABLE t_copy LIKE t; +INSERT INTO t_copy SELECT * FROM t; + +--enable_info +ALTER TABLE t ADD COLUMN r INT UNSIGNED NOT NULL AUTO_INCREMENT, +ADD UNIQUE KEY (r,b); +ALTER TABLE t_copy ADD COLUMN r INT UNSIGNED NOT NULL AUTO_INCREMENT, +ADD UNIQUE KEY (r,b), ALGORITHM=COPY; +--disable_info +SELECT * FROM t; +SELECT * FROM t_copy; +DROP TABLE t,t_copy; diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 2167bea8d7c..80bf7ef17fe 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -1,6 +1,6 @@ /* - Copyright (c) 2005, 2017, Oracle and/or its affiliates. - Copyright (c) 2009, 2017, MariaDB + Copyright (c) 2005, 2019, Oracle and/or its affiliates. + Copyright (c) 2009, 2019, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -8329,7 +8329,12 @@ bool ha_partition::inplace_alter_table(TABLE *altered_table, for (index= 0; index < m_tot_parts && !error; index++) { - ha_alter_info->handler_ctx= part_inplace_ctx->handler_ctx_array[index]; + if ((ha_alter_info->handler_ctx= + part_inplace_ctx->handler_ctx_array[index]) != NULL + && index != 0) + ha_alter_info->handler_ctx->set_shared_data + (*part_inplace_ctx->handler_ctx_array[index - 1]); + if (m_file[index]->ha_inplace_alter_table(altered_table, ha_alter_info)) error= true; diff --git a/sql/handler.h b/sql/handler.h index af492e75da6..99dfefd4c5a 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -1,8 +1,8 @@ #ifndef HANDLER_INCLUDED #define HANDLER_INCLUDED /* - Copyright (c) 2000, 2016, Oracle and/or its affiliates. - Copyright (c) 2009, 2018, MariaDB + Copyright (c) 2000, 2019, Oracle and/or its affiliates. + Copyright (c) 2009, 2019, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -1833,6 +1833,7 @@ public: inplace_alter_handler_ctx() {} virtual ~inplace_alter_handler_ctx() {} + virtual void set_shared_data(const inplace_alter_handler_ctx& ctx) {} }; diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index fbded2f0a53..0d0982fa498 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2005, 2018, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2005, 2019, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2013, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under @@ -2178,6 +2178,23 @@ struct ha_innobase_inplace_ctx : public inplace_alter_handler_ctx @return whether the table will be rebuilt */ bool need_rebuild () const { return(old_table != new_table); } + /** Share context between partitions. + @param[in] ctx context from another partition of the table */ + void set_shared_data(const inplace_alter_handler_ctx& ctx) + { + if (add_autoinc != ULINT_UNDEFINED) { + const ha_innobase_inplace_ctx& ha_ctx = + static_cast + (ctx); + /* When adding an AUTO_INCREMENT column to a + partitioned InnoDB table, we must share the + sequence for all partitions. */ + ut_ad(ha_ctx.add_autoinc == add_autoinc); + ut_ad(ha_ctx.sequence.last()); + sequence = ha_ctx.sequence; + } + } + private: // Disable copying ha_innobase_inplace_ctx(const ha_innobase_inplace_ctx&); diff --git a/storage/xtradb/handler/handler0alter.cc b/storage/xtradb/handler/handler0alter.cc index 0a246d897c1..808f8529a77 100644 --- a/storage/xtradb/handler/handler0alter.cc +++ b/storage/xtradb/handler/handler0alter.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2005, 2018, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2005, 2019, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2017, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under @@ -2181,6 +2181,23 @@ struct ha_innobase_inplace_ctx : public inplace_alter_handler_ctx @return whether the table will be rebuilt */ bool need_rebuild () const { return(old_table != new_table); } + /** Share context between partitions. + @param[in] ctx context from another partition of the table */ + void set_shared_data(const inplace_alter_handler_ctx& ctx) + { + if (add_autoinc != ULINT_UNDEFINED) { + const ha_innobase_inplace_ctx& ha_ctx = + static_cast + (ctx); + /* When adding an AUTO_INCREMENT column to a + partitioned InnoDB table, we must share the + sequence for all partitions. */ + ut_ad(ha_ctx.add_autoinc == add_autoinc); + ut_ad(ha_ctx.sequence.last()); + sequence = ha_ctx.sequence; + } + } + private: // Disable copying ha_innobase_inplace_ctx(const ha_innobase_inplace_ctx&);