From fe75fbd68e861eada772eff05f20945d824e18ce Mon Sep 17 00:00:00 2001 From: Nayuta Yanagisawa Date: Fri, 29 Oct 2021 19:04:53 +0900 Subject: MDEV-26127 Assertion `err != DB_DUPLICATE_KEY' failed or InnoDB: Failing assertion: id != 0 on ALTER ... REBUILD PARTITION During rebuild of partition, the partitioning engine calls alter_close_table(), which does not unlock and close some table instances of the target table. Then, the engine fails to rename partitions because there are table instances that are still locked. Closing all the table instance of the target table fixes the bug. --- mysql-test/suite/parts/inc/part_alter_values.inc | 14 ++++++++++--- .../suite/parts/r/partition_alter_innodb.result | 10 ++++++++++ .../suite/parts/r/partition_alter_maria.result | 10 ++++++++++ .../suite/parts/r/partition_alter_myisam.result | 10 ++++++++++ sql/sql_partition.cc | 23 ++++++++++++++++++---- 5 files changed, 60 insertions(+), 7 deletions(-) diff --git a/mysql-test/suite/parts/inc/part_alter_values.inc b/mysql-test/suite/parts/inc/part_alter_values.inc index ac69169a9ca..20f3e063ba1 100644 --- a/mysql-test/suite/parts/inc/part_alter_values.inc +++ b/mysql-test/suite/parts/inc/part_alter_values.inc @@ -36,12 +36,20 @@ ALTER TABLE t1 REORGANIZE PARTITION p1 INTO ); DROP TABLE t1; -# -# MDEV-15456 Server crashes upon adding or dropping a partition in ALTER under LOCK TABLE after ER_SAME_NAME_PARTITION -# +--echo # +--echo # MDEV-15456 Server crashes upon adding or dropping a partition in ALTER under LOCK TABLE after ER_SAME_NAME_PARTITION +--echo # --eval create table t1 (i int) engine=$engine partition by range(i) (partition p0 values less than (10)) lock table t1 write; --error ER_SAME_NAME_PARTITION alter table t1 add partition (partition p0 values less than (20)); alter table t1 add partition (partition p1 values less than (20)) /* comment */; drop table t1; + +--echo # +--echo # MDEV-26127 Assertion `err != DB_DUPLICATE_KEY' failed or InnoDB: Failing assertion: id != 0 on ALTER ... REBUILD PARTITION +--echo # +--eval CREATE TABLE t1 (c INT) ENGINE=$engine PARTITION BY KEY(c) PARTITIONS 4; +LOCK TABLES t1 WRITE, t1 AS a READ; +ALTER TABLE t1 REBUILD PARTITION p0; +DROP TABLE t1; diff --git a/mysql-test/suite/parts/r/partition_alter_innodb.result b/mysql-test/suite/parts/r/partition_alter_innodb.result index f3921a1db26..5d02ce4c00e 100644 --- a/mysql-test/suite/parts/r/partition_alter_innodb.result +++ b/mysql-test/suite/parts/r/partition_alter_innodb.result @@ -42,9 +42,19 @@ PARTITION p3 VALUES IN (4,5,6) ); ERROR HY000: Syntax error: LIST PARTITIONING requires definition of VALUES IN for each partition DROP TABLE t1; +# +# MDEV-15456 Server crashes upon adding or dropping a partition in ALTER under LOCK TABLE after ER_SAME_NAME_PARTITION +# create table t1 (i int) engine=InnoDB partition by range(i) (partition p0 values less than (10)); lock table t1 write; alter table t1 add partition (partition p0 values less than (20)); ERROR HY000: Duplicate partition name p0 alter table t1 add partition (partition p1 values less than (20)) /* comment */; drop table t1; +# +# MDEV-26127 Assertion `err != DB_DUPLICATE_KEY' failed or InnoDB: Failing assertion: id != 0 on ALTER ... REBUILD PARTITION +# +CREATE TABLE t1 (c INT) ENGINE=InnoDB PARTITION BY KEY(c) PARTITIONS 4;; +LOCK TABLES t1 WRITE, t1 AS a READ; +ALTER TABLE t1 REBUILD PARTITION p0; +DROP TABLE t1; diff --git a/mysql-test/suite/parts/r/partition_alter_maria.result b/mysql-test/suite/parts/r/partition_alter_maria.result index 77f511d9b3b..a49639482c0 100644 --- a/mysql-test/suite/parts/r/partition_alter_maria.result +++ b/mysql-test/suite/parts/r/partition_alter_maria.result @@ -69,9 +69,19 @@ PARTITION p3 VALUES IN (4,5,6) ); ERROR HY000: Syntax error: LIST PARTITIONING requires definition of VALUES IN for each partition DROP TABLE t1; +# +# MDEV-15456 Server crashes upon adding or dropping a partition in ALTER under LOCK TABLE after ER_SAME_NAME_PARTITION +# create table t1 (i int) engine=Aria partition by range(i) (partition p0 values less than (10)); lock table t1 write; alter table t1 add partition (partition p0 values less than (20)); ERROR HY000: Duplicate partition name p0 alter table t1 add partition (partition p1 values less than (20)) /* comment */; drop table t1; +# +# MDEV-26127 Assertion `err != DB_DUPLICATE_KEY' failed or InnoDB: Failing assertion: id != 0 on ALTER ... REBUILD PARTITION +# +CREATE TABLE t1 (c INT) ENGINE=Aria PARTITION BY KEY(c) PARTITIONS 4;; +LOCK TABLES t1 WRITE, t1 AS a READ; +ALTER TABLE t1 REBUILD PARTITION p0; +DROP TABLE t1; diff --git a/mysql-test/suite/parts/r/partition_alter_myisam.result b/mysql-test/suite/parts/r/partition_alter_myisam.result index ce3e04d6c97..afbb4c21353 100644 --- a/mysql-test/suite/parts/r/partition_alter_myisam.result +++ b/mysql-test/suite/parts/r/partition_alter_myisam.result @@ -42,12 +42,22 @@ PARTITION p3 VALUES IN (4,5,6) ); ERROR HY000: Syntax error: LIST PARTITIONING requires definition of VALUES IN for each partition DROP TABLE t1; +# +# MDEV-15456 Server crashes upon adding or dropping a partition in ALTER under LOCK TABLE after ER_SAME_NAME_PARTITION +# create table t1 (i int) engine=MyISAM partition by range(i) (partition p0 values less than (10)); lock table t1 write; alter table t1 add partition (partition p0 values less than (20)); ERROR HY000: Duplicate partition name p0 alter table t1 add partition (partition p1 values less than (20)) /* comment */; drop table t1; +# +# MDEV-26127 Assertion `err != DB_DUPLICATE_KEY' failed or InnoDB: Failing assertion: id != 0 on ALTER ... REBUILD PARTITION +# +CREATE TABLE t1 (c INT) ENGINE=MyISAM PARTITION BY KEY(c) PARTITIONS 4;; +LOCK TABLES t1 WRITE, t1 AS a READ; +ALTER TABLE t1 REBUILD PARTITION p0; +DROP TABLE t1; create table t1 ( c1 int, c2 int, c3 varchar(100)) delay_key_write=1 partition by key(c1) ( partition p01 data directory = 'MYSQL_TMP_DIR' diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 2334286b039..2453e0da159 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2005, 2017, Oracle and/or its affiliates. - Copyright (c) 2009, 2018, MariaDB + Copyright (c) 2009, 2022, 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 @@ -6408,13 +6408,28 @@ static void alter_partition_lock_handling(ALTER_PARTITION_PARAM_TYPE *lpt) static int alter_close_table(ALTER_PARTITION_PARAM_TYPE *lpt) { + TABLE_SHARE *share= lpt->table->s; + char key[MAX_DBKEY_LENGTH]; + size_t key_length= share->table_cache_key.length; + memcpy(key, share->table_cache_key.str, key_length); + int error= 0; DBUG_ENTER("alter_close_table"); if (lpt->table->db_stat) { - mysql_lock_remove(lpt->thd, lpt->thd->lock, lpt->table); - lpt->table->file->ha_close(); - lpt->table->db_stat= 0; // Mark file closed + for (TABLE *table= lpt->thd->open_tables; table; (table= table->next)) + { + if (table->s->table_cache_key.length == key_length && + !memcmp(table->s->table_cache_key.str, key, key_length)) + { + mysql_lock_remove(lpt->thd, lpt->thd->lock, table); + if ((error= table->file->ha_close())) + { + DBUG_RETURN(error); + } + table->db_stat= 0; // Mark file closed + } + } } DBUG_RETURN(0); } -- cgit v1.2.1