Commit 188aae65 authored by Vlad Lesin's avatar Vlad Lesin

MDEV-26224 InnoDB fails to remove AUTO_INCREMENT attribute

Reset dict_table_t::persistent_autoinc when inplace alter table is
committed successfully.
parent aec85607
CREATE TABLE t1 (c INT AUTO_INCREMENT NULL UNIQUE) ENGINE=InnoDB;
ALTER TABLE t1 MODIFY c INT NULL, ALGORITHM=INSTANT;
INSERT INTO t1 SET c=1;
CREATE TABLE t2 (c INT AUTO_INCREMENT NULL UNIQUE) ENGINE=InnoDB;
ALTER TABLE t2 MODIFY c INT NULL, FORCE, ALGORITHM=INPLACE;
INSERT INTO t2 SET c=1;
CREATE TABLE t3 (c INT AUTO_INCREMENT NULL UNIQUE) ENGINE=InnoDB;
ALTER TABLE t3 MODIFY c INT NULL, ALGORITHM=INPLACE;
INSERT INTO t3 SET c=1;
CREATE TABLE t4 (c1 INT AUTO_INCREMENT NULL UNIQUE, c2 INT) ENGINE=InnoDB;
ALTER TABLE t4 MODIFY c1 INT NULL, CHANGE COLUMN c2 c3 INT, ALGORITHM=INPLACE;
INSERT INTO t4 SET c1=1;
CREATE TABLE t5 (c1 INT AUTO_INCREMENT NULL UNIQUE, c2 INT, c3 INTEGER GENERATED ALWAYS AS (c2)) ENGINE=InnoDB;
ALTER TABLE t5 MODIFY c1 INT NULL, MODIFY COLUMN c2 INT FIRST, ALGORITHM=INPLACE;
INSERT INTO t5 SET c1=1;
CREATE TABLE t6 (c INT AUTO_INCREMENT NULL UNIQUE) ENGINE=InnoDB
PARTITION BY LIST(c) (
PARTITION p1 VALUES IN (1),
PARTITION p2 VALUES IN (2)
);
ALTER TABLE t6 MODIFY c INT NULL, ALGORITHM=INSTANT;
INSERT INTO t6 SET c=1;
INSERT INTO t6 SET c=2;
CREATE TABLE t7 (c INT AUTO_INCREMENT NULL UNIQUE) ENGINE=InnoDB
PARTITION BY LIST(c) (
PARTITION p1 VALUES IN (1),
PARTITION p2 VALUES IN (2)
);
ALTER TABLE t7 MODIFY c INT NULL, ALGORITHM=INPLACE;
INSERT INTO t7 SET c=1;
INSERT INTO t7 SET c=2;
CREATE TABLE t8 (c1 INT AUTO_INCREMENT NULL UNIQUE, c2 INT) ENGINE=InnoDB
PARTITION BY LIST(c1) (
PARTITION p1 VALUES IN (1), PARTITION p2 VALUES IN (2));
ALTER TABLE t8 MODIFY c1 INT NULL, CHANGE COLUMN c2 c3 INT, ALGORITHM=INPLACE;
INSERT INTO t8 SET c1=1;
INSERT INTO t8 SET c1=2;
FLUSH TABLES t1, t2, t3, t4, t5, t6, t7, t8 FOR EXPORT;
AUTO_INCREMENT not partitioned: 0 0 0 0 0
AUTO_INCREMENT partitioned: (0, 0) (0, 0) (0, 0)
UNLOCK TABLES;
DROP TABLE t1, t2, t3, t4, t5, t6, t7, t8;
# Test the ability to remove AUTO_INCREMENT attribute
--source include/have_innodb.inc
--source include/have_partition.inc
CREATE TABLE t1 (c INT AUTO_INCREMENT NULL UNIQUE) ENGINE=InnoDB;
ALTER TABLE t1 MODIFY c INT NULL, ALGORITHM=INSTANT;
INSERT INTO t1 SET c=1;
CREATE TABLE t2 (c INT AUTO_INCREMENT NULL UNIQUE) ENGINE=InnoDB;
ALTER TABLE t2 MODIFY c INT NULL, FORCE, ALGORITHM=INPLACE;
INSERT INTO t2 SET c=1;
CREATE TABLE t3 (c INT AUTO_INCREMENT NULL UNIQUE) ENGINE=InnoDB;
ALTER TABLE t3 MODIFY c INT NULL, ALGORITHM=INPLACE;
INSERT INTO t3 SET c=1;
CREATE TABLE t4 (c1 INT AUTO_INCREMENT NULL UNIQUE, c2 INT) ENGINE=InnoDB;
ALTER TABLE t4 MODIFY c1 INT NULL, CHANGE COLUMN c2 c3 INT, ALGORITHM=INPLACE;
INSERT INTO t4 SET c1=1;
CREATE TABLE t5 (c1 INT AUTO_INCREMENT NULL UNIQUE, c2 INT, c3 INTEGER GENERATED ALWAYS AS (c2)) ENGINE=InnoDB;
# ha_innobase::commit_inplace_alter_table() should invoke innobase_reload_table()
ALTER TABLE t5 MODIFY c1 INT NULL, MODIFY COLUMN c2 INT FIRST, ALGORITHM=INPLACE;
INSERT INTO t5 SET c1=1;
CREATE TABLE t6 (c INT AUTO_INCREMENT NULL UNIQUE) ENGINE=InnoDB
PARTITION BY LIST(c) (
PARTITION p1 VALUES IN (1),
PARTITION p2 VALUES IN (2)
);
ALTER TABLE t6 MODIFY c INT NULL, ALGORITHM=INSTANT;
INSERT INTO t6 SET c=1;
INSERT INTO t6 SET c=2;
CREATE TABLE t7 (c INT AUTO_INCREMENT NULL UNIQUE) ENGINE=InnoDB
PARTITION BY LIST(c) (
PARTITION p1 VALUES IN (1),
PARTITION p2 VALUES IN (2)
);
ALTER TABLE t7 MODIFY c INT NULL, ALGORITHM=INPLACE;
INSERT INTO t7 SET c=1;
INSERT INTO t7 SET c=2;
CREATE TABLE t8 (c1 INT AUTO_INCREMENT NULL UNIQUE, c2 INT) ENGINE=InnoDB
PARTITION BY LIST(c1) (
PARTITION p1 VALUES IN (1), PARTITION p2 VALUES IN (2));
ALTER TABLE t8 MODIFY c1 INT NULL, CHANGE COLUMN c2 c3 INT, ALGORITHM=INPLACE;
INSERT INTO t8 SET c1=1;
INSERT INTO t8 SET c1=2;
FLUSH TABLES t1, t2, t3, t4, t5, t6, t7, t8 FOR EXPORT;
--let INNODB_PAGE_SIZE=`select @@innodb_page_size`
--let MYSQLD_DATADIR = `SELECT @@datadir`
--perl
my $ps= $ENV{INNODB_PAGE_SIZE};
my $PAGE_HEADER = 38;
my $PAGE_ROOT_AUTO_INC = 18;
print "AUTO_INCREMENT not partitioned: ";
for (my $i = 1; $i <= 5; ++$i) {
my $autoinc= read_autoinc("$ENV{MYSQLD_DATADIR}/test/t$i.ibd");
print "$autoinc ";
}
print "\n";
print "AUTO_INCREMENT partitioned: ";
for (my $i = 6; $i <= 8; ++$i) {
my $p1= read_autoinc("$ENV{MYSQLD_DATADIR}/test/t$i#P#p1.ibd");
my $p2= read_autoinc("$ENV{MYSQLD_DATADIR}/test/t$i#P#p2.ibd");
print "($p1, $p2) ";
}
print "\n";
sub read_autoinc {
my $file= shift;
open(FILE, "<", $file) || die "Unable to open $file\n";
sysseek(FILE, 3*$ps + $PAGE_HEADER + $PAGE_ROOT_AUTO_INC + 4, 0)
|| die "Unable to seek $file\n";
die "Unable to read $file\n" unless sysread(FILE, $_, 4) == 4;
my $t1=unpack("N",$_);
close(FILE);
return $t1;
}
EOF
UNLOCK TABLES;
DROP TABLE t1, t2, t3, t4, t5, t6, t7, t8;
...@@ -10437,7 +10437,16 @@ bool ha_partition::commit_inplace_alter_table(TABLE *altered_table, ...@@ -10437,7 +10437,16 @@ bool ha_partition::commit_inplace_alter_table(TABLE *altered_table,
Loop over all other partitions as to follow the protocol! Loop over all other partitions as to follow the protocol!
*/ */
uint i; uint i;
DBUG_ASSERT(0); /*
InnoDB does not set ha_alter_info->group_commit_ctx to NULL in the
case if autoincrement attribute is necessary to reset for all
partitions for INNOBASE_INPLACE_IGNORE handler flags. It does not
affect durability, because it is solely about updating the InnoDB data
dictionary caches (one InnoDB dict_table_t per partition or
sub-partition).
*/
DBUG_ASSERT(table->found_next_number_field
&& !altered_table->found_next_number_field);
for (i= 1; i < m_tot_parts; i++) for (i= 1; i < m_tot_parts; i++)
{ {
ha_alter_info->handler_ctx= part_inplace_ctx->handler_ctx_array[i]; ha_alter_info->handler_ctx= part_inplace_ctx->handler_ctx_array[i];
......
...@@ -10711,6 +10711,10 @@ commit_cache_norebuild( ...@@ -10711,6 +10711,10 @@ commit_cache_norebuild(
: NULL; : NULL;
DBUG_ASSERT((ctx->new_table->fts == NULL) DBUG_ASSERT((ctx->new_table->fts == NULL)
== (ctx->new_table->fts_doc_id_index == NULL)); == (ctx->new_table->fts_doc_id_index == NULL));
if (table->found_next_number_field
&& !altered_table->found_next_number_field) {
ctx->prebuilt->table->persistent_autoinc = 0;
}
DBUG_RETURN(found); DBUG_RETURN(found);
} }
...@@ -11035,7 +11039,15 @@ ha_innobase::commit_inplace_alter_table( ...@@ -11035,7 +11039,15 @@ ha_innobase::commit_inplace_alter_table(
if (!(ha_alter_info->handler_flags & ~INNOBASE_INPLACE_IGNORE)) { if (!(ha_alter_info->handler_flags & ~INNOBASE_INPLACE_IGNORE)) {
DBUG_ASSERT(!ctx0); DBUG_ASSERT(!ctx0);
MONITOR_ATOMIC_DEC(MONITOR_PENDING_ALTER_TABLE); MONITOR_ATOMIC_DEC(MONITOR_PENDING_ALTER_TABLE);
ha_alter_info->group_commit_ctx = NULL; if (table->found_next_number_field
&& !altered_table->found_next_number_field) {
m_prebuilt->table->persistent_autoinc = 0;
/* Don't reset ha_alter_info->group_commit_ctx to make
partitions engine to call this function for all
partitions. */
}
else
ha_alter_info->group_commit_ctx = NULL;
DBUG_RETURN(false); DBUG_RETURN(false);
} }
...@@ -11543,6 +11555,8 @@ ha_innobase::commit_inplace_alter_table( ...@@ -11543,6 +11555,8 @@ ha_innobase::commit_inplace_alter_table(
row_mysql_unlock_data_dictionary(trx); row_mysql_unlock_data_dictionary(trx);
trx->free(); trx->free();
MONITOR_ATOMIC_DEC(MONITOR_PENDING_ALTER_TABLE); MONITOR_ATOMIC_DEC(MONITOR_PENDING_ALTER_TABLE);
/* There is no need to reset dict_table_t::persistent_autoinc
as the table is reloaded */
DBUG_RETURN(false); DBUG_RETURN(false);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment