summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThirunarayanan Balathandayuthapani <thiru@mariadb.com>2021-11-12 17:46:35 +0530
committerThirunarayanan Balathandayuthapani <thiru@mariadb.com>2021-11-12 17:46:35 +0530
commitd270525dfde86bcb92a2327234a0954083e14a94 (patch)
tree89b8a1dc169f97f8f87ac40d47c7bc5cb90fe98c
parentc5380c30b59da88bba2a6394c7599a420016ccdd (diff)
downloadmariadb-git-d270525dfde86bcb92a2327234a0954083e14a94.tar.gz
MDEV-23805 Make Online DDL to Instant DDL when table is emptybb-10.4-MDEV-23805
- In ha_innobase::prepare_inplace_alter_table(), InnoDB should check whether the table is empty. If the table is empty then server should avoid downgrading the MDL after prepare phase. It is more like instant alter, does change only in dicationary and metadata. - Changed few debug test case to make non-empty DDL table
-rw-r--r--mysql-test/suite/gcol/r/virtual_index_drop.result3
-rw-r--r--mysql-test/suite/gcol/t/virtual_index_drop.test2
-rw-r--r--mysql-test/suite/innodb/r/alter_candidate_key.result2
-rw-r--r--mysql-test/suite/innodb/r/alter_not_null_debug.result2
-rw-r--r--mysql-test/suite/innodb/r/alter_primary_key.result2
-rw-r--r--mysql-test/suite/innodb/r/ddl_purge.result1
-rw-r--r--mysql-test/suite/innodb/r/innodb-alter-tempfile.result2
-rw-r--r--mysql-test/suite/innodb/r/innodb-index-debug.result5
-rw-r--r--mysql-test/suite/innodb/r/innodb-index-online.result1
-rw-r--r--mysql-test/suite/innodb/r/instant_alter_debug.result3
-rw-r--r--mysql-test/suite/innodb/t/alter_candidate_key.test2
-rw-r--r--mysql-test/suite/innodb/t/alter_not_null_debug.test2
-rw-r--r--mysql-test/suite/innodb/t/alter_primary_key.test1
-rw-r--r--mysql-test/suite/innodb/t/ddl_purge.test1
-rw-r--r--mysql-test/suite/innodb/t/innodb-alter-tempfile.test2
-rw-r--r--mysql-test/suite/innodb/t/innodb-index-debug.test2
-rw-r--r--mysql-test/suite/innodb/t/innodb-index-online.test1
-rw-r--r--mysql-test/suite/innodb/t/instant_alter_debug.test3
-rw-r--r--mysql-test/suite/innodb_fts/r/misc_debug.result2
-rw-r--r--mysql-test/suite/innodb_fts/t/misc_debug.test1
-rw-r--r--sql/handler.h3
-rw-r--r--sql/sql_table.cc7
-rw-r--r--storage/innobase/handler/handler0alter.cc36
23 files changed, 73 insertions, 13 deletions
diff --git a/mysql-test/suite/gcol/r/virtual_index_drop.result b/mysql-test/suite/gcol/r/virtual_index_drop.result
index 012e61be459..45ee4843b7c 100644
--- a/mysql-test/suite/gcol/r/virtual_index_drop.result
+++ b/mysql-test/suite/gcol/r/virtual_index_drop.result
@@ -25,6 +25,7 @@ t1 CREATE TABLE `t1` (
) ENGINE=InnoDB DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1(f1 INT, f2 INT AS (f1) VIRTUAL)ENGINE=InnoDB;
+INSERT INTO t1(f1) VALUES(1);
SET DEBUG_DBUG="+d,create_index_fail";
SET DEBUG_SYNC="innodb_inplace_alter_table_enter SIGNAL con1_go WAIT_FOR alter_signal";
ALTER TABLE t1 ADD COLUMN f3 INT AS (f1) VIRTUAL, ADD INDEX(f2, f3);
@@ -33,6 +34,7 @@ SET DEBUG_SYNC="now WAIT_FOR con1_go";
BEGIN;
SELECT * FROM t1;
f1 f2
+1 1
SET DEBUG_SYNC="now SIGNAL alter_signal";
connection default;
ERROR 23000: Duplicate entry '' for key '*UNKNOWN*'
@@ -47,6 +49,7 @@ t1 CREATE TABLE `t1` (
) ENGINE=InnoDB DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1(f1 INT, f2 INT AS (f1) VIRTUAL)ENGINE=InnoDB;
+INSERT INTO t1(f1) VALUES(1);
SET DEBUG_DBUG="+d,create_index_fail";
SET DEBUG_SYNC="innodb_inplace_alter_table_enter SIGNAL con1_go WAIT_FOR alter_signal";
ALTER TABLE t1 ADD INDEX(f2);
diff --git a/mysql-test/suite/gcol/t/virtual_index_drop.test b/mysql-test/suite/gcol/t/virtual_index_drop.test
index 016832b9e6d..e1ec43f75e5 100644
--- a/mysql-test/suite/gcol/t/virtual_index_drop.test
+++ b/mysql-test/suite/gcol/t/virtual_index_drop.test
@@ -29,6 +29,7 @@ DROP TABLE t1;
# new_vcol_info in index when rollback of alter happens
CREATE TABLE t1(f1 INT, f2 INT AS (f1) VIRTUAL)ENGINE=InnoDB;
+INSERT INTO t1(f1) VALUES(1);
SET DEBUG_DBUG="+d,create_index_fail";
SET DEBUG_SYNC="innodb_inplace_alter_table_enter SIGNAL con1_go WAIT_FOR alter_signal";
SEND ALTER TABLE t1 ADD COLUMN f3 INT AS (f1) VIRTUAL, ADD INDEX(f2, f3);
@@ -47,6 +48,7 @@ SHOW CREATE TABLE t1;
DROP TABLE t1;
CREATE TABLE t1(f1 INT, f2 INT AS (f1) VIRTUAL)ENGINE=InnoDB;
+INSERT INTO t1(f1) VALUES(1);
SET DEBUG_DBUG="+d,create_index_fail";
SET DEBUG_SYNC="innodb_inplace_alter_table_enter SIGNAL con1_go WAIT_FOR alter_signal";
send ALTER TABLE t1 ADD INDEX(f2);
diff --git a/mysql-test/suite/innodb/r/alter_candidate_key.result b/mysql-test/suite/innodb/r/alter_candidate_key.result
index 23989e0da5f..79cb225e3b5 100644
--- a/mysql-test/suite/innodb/r/alter_candidate_key.result
+++ b/mysql-test/suite/innodb/r/alter_candidate_key.result
@@ -34,6 +34,7 @@ CREATE TABLE t1(f1 INT, f2 INT,
PRIMARY KEY(f1, f2),
UNIQUE INDEX uidx2 (f1, f2),
UNIQUE INDEX uidx1 (f2))ENGINE=InnoDB;
+INSERT INTO t1 VALUES(2, 2);
ALTER TABLE t1 DROP PRIMARY KEY;
SHOW CREATE TABLE t1;
Table Create Table
@@ -66,6 +67,7 @@ test.t1 check status OK
DROP TABLE t1;
SET SQL_MODE= strict_trans_tables;
CREATE TABLE t1(a INT UNIQUE) ENGINE=InnoDB;
+INSERT INTO t1 VALUES(1);
SET DEBUG_SYNC='row_log_table_apply1_before SIGNAL dml WAIT_FOR dml_done';
ALTER TABLE t1 MODIFY COLUMN a INT NOT NULL;
connection con1;
diff --git a/mysql-test/suite/innodb/r/alter_not_null_debug.result b/mysql-test/suite/innodb/r/alter_not_null_debug.result
index 0c1af03159d..ff77eaf54c5 100644
--- a/mysql-test/suite/innodb/r/alter_not_null_debug.result
+++ b/mysql-test/suite/innodb/r/alter_not_null_debug.result
@@ -80,6 +80,7 @@ SET DEBUG_SYNC='RESET';
#
CREATE TABLE t1 (f VARCHAR(8) CHARACTER SET latin1 COLLATE latin1_swedish_ci)
ENGINE=InnoDB;
+INSERT INTO t1 VALUES('ZERO');
connection con1;
SET DEBUG_SYNC = 'row_log_table_apply1_before SIGNAL scanned WAIT_FOR insert_done';
ALTER TABLE t1 MODIFY f VARCHAR(256) COLLATE latin1_german2_ci NOT NULL;
@@ -96,5 +97,6 @@ ALTER TABLE t1 CHANGE f eins VARCHAR(257) COLLATE latin1_german1_ci NOT NULL,
ALGORITHM=INSTANT;
SELECT * FROM t1;
eins
+ZERO
one
DROP TABLE t1;
diff --git a/mysql-test/suite/innodb/r/alter_primary_key.result b/mysql-test/suite/innodb/r/alter_primary_key.result
index afe687871f3..b478691af1f 100644
--- a/mysql-test/suite/innodb/r/alter_primary_key.result
+++ b/mysql-test/suite/innodb/r/alter_primary_key.result
@@ -4,6 +4,7 @@
#
CREATE TABLE t0 (pk INT PRIMARY KEY) ENGINE=InnoDB;
CREATE TABLE t1 (c CHAR(2) NOT NULL) ENGINE=InnoDB;
+INSERT INTO t1 VALUES('cd');
connect con1,localhost,root,,;
BEGIN;
INSERT INTO t0 VALUES(1);
@@ -21,6 +22,7 @@ ERROR 23000: Duplicate entry 'a' for key 'PRIMARY'
SET DEBUG_SYNC='RESET';
SELECT * FROM t1;
c
+cd
ab
ac
DROP TABLE t0,t1;
diff --git a/mysql-test/suite/innodb/r/ddl_purge.result b/mysql-test/suite/innodb/r/ddl_purge.result
index 45f4c99e97b..275be16b2d7 100644
--- a/mysql-test/suite/innodb/r/ddl_purge.result
+++ b/mysql-test/suite/innodb/r/ddl_purge.result
@@ -1,5 +1,6 @@
CREATE TABLE t0 (pk INT PRIMARY KEY) ENGINE=InnoDB;
CREATE TABLE t1 (pk INT PRIMARY KEY, b INT) ENGINE=InnoDB;
+INSERT INTO t1 VALUES(100, 100);
connect con1,localhost,root,,test;
BEGIN;
INSERT INTO t0 SET pk=1;
diff --git a/mysql-test/suite/innodb/r/innodb-alter-tempfile.result b/mysql-test/suite/innodb/r/innodb-alter-tempfile.result
index 0716f3da23c..57229d05133 100644
--- a/mysql-test/suite/innodb/r/innodb-alter-tempfile.result
+++ b/mysql-test/suite/innodb/r/innodb-alter-tempfile.result
@@ -61,7 +61,7 @@ connect con1,localhost,root,,;
BEGIN;
DELETE FROM mysql.innodb_table_stats;
connect con2,localhost,root,,;
-SET DEBUG_SYNC='inplace_after_index_build SIGNAL blocked WAIT_FOR ever';
+SET DEBUG_SYNC='innodb_inplace_alter_table_enter SIGNAL blocked WAIT_FOR ever';
ALTER TABLE t1 FORCE;
connection default;
SET DEBUG_SYNC='now WAIT_FOR blocked';
diff --git a/mysql-test/suite/innodb/r/innodb-index-debug.result b/mysql-test/suite/innodb/r/innodb-index-debug.result
index daef31d2caa..2eba29e6c28 100644
--- a/mysql-test/suite/innodb/r/innodb-index-debug.result
+++ b/mysql-test/suite/innodb/r/innodb-index-debug.result
@@ -81,6 +81,7 @@ COUNT(k1) k2 k3
drop table t1;
create table t1(k1 int auto_increment primary key,
k2 char(200),k3 char(200))engine=innodb;
+INSERT INTO t1 VALUES(1, "test", "test");
SET DEBUG_SYNC= 'row_merge_after_scan
SIGNAL opened WAIT_FOR flushed';
ALTER TABLE t1 FORCE, ADD COLUMN k4 int;
@@ -100,6 +101,7 @@ SELECT COUNT(k1),k2,k3 FROM t1 GROUP BY k2,k3;
COUNT(k1) k2 k3
480 aaa bbb
480 aaaa bbbb
+1 test test
disconnect con1;
connection default;
show create table t1;
@@ -109,7 +111,7 @@ t1 CREATE TABLE `t1` (
`k2` char(200) DEFAULT NULL,
`k3` char(200) DEFAULT NULL,
PRIMARY KEY (`k1`)
-) ENGINE=InnoDB AUTO_INCREMENT=1023 DEFAULT CHARSET=latin1
+) ENGINE=InnoDB AUTO_INCREMENT=1024 DEFAULT CHARSET=latin1
drop table t1;
drop table t480;
#
@@ -117,6 +119,7 @@ drop table t480;
# in online table rebuild
#
CREATE TABLE t1 (j INT UNIQUE, i INT UNIQUE) ENGINE=InnoDB;
+INSERT INTO t1 VALUES(2, 2);
connect con1,localhost,root,,test;
SET DEBUG_SYNC='row_log_table_apply1_before SIGNAL built WAIT_FOR log';
ALTER TABLE t1 DROP j, FORCE;
diff --git a/mysql-test/suite/innodb/r/innodb-index-online.result b/mysql-test/suite/innodb/r/innodb-index-online.result
index 8eebece46b5..f101a63a6ed 100644
--- a/mysql-test/suite/innodb/r/innodb-index-online.result
+++ b/mysql-test/suite/innodb/r/innodb-index-online.result
@@ -509,6 +509,7 @@ DROP TABLE t1;
# MDEV-13205 assertion !dict_index_is_online_ddl(index) upon ALTER TABLE
#
CREATE TABLE t1 (c VARCHAR(64)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES('foo');
SET DEBUG_SYNC = 'row_log_apply_before SIGNAL t1u_created WAIT_FOR dup_done';
ALTER TABLE t1 ADD UNIQUE(c);
connection con1;
diff --git a/mysql-test/suite/innodb/r/instant_alter_debug.result b/mysql-test/suite/innodb/r/instant_alter_debug.result
index 359eb1fc384..26db222ca82 100644
--- a/mysql-test/suite/innodb/r/instant_alter_debug.result
+++ b/mysql-test/suite/innodb/r/instant_alter_debug.result
@@ -171,6 +171,7 @@ connect stop_purge,localhost,root;
START TRANSACTION WITH CONSISTENT SNAPSHOT;
connect ddl,localhost,root,,test;
DELETE FROM t1;
+INSERT INTO t1 VALUES(1, 2);
SET DEBUG_SYNC='row_log_table_apply1_before SIGNAL copied WAIT_FOR logged';
ALTER TABLE t1 FORCE;
connection default;
@@ -449,6 +450,7 @@ DROP TABLE t1;
CREATE TABLE t1
(a INT NOT NULL, b INT, c INT, d INT, e INT, f INT, g INT, h INT, i TEXT)
ENGINE=InnoDB;
+INSERT INTO t1 VALUES(1, 2, 3, 4, 5, 6, 7, 8, "test");
ALTER TABLE t1 MODIFY a INT NULL;
SET DEBUG_SYNC='innodb_inplace_alter_table_enter SIGNAL alter WAIT_FOR go';
ALTER TABLE t1 ADD PRIMARY KEY (a);
@@ -462,6 +464,7 @@ connection default;
disconnect con1;
SELECT * FROM t1;
a b c d e f g h i
+1 2 3 4 5 6 7 8 test
DROP TABLE t1;
SET DEBUG_SYNC=RESET;
# End of 10.4 tests
diff --git a/mysql-test/suite/innodb/t/alter_candidate_key.test b/mysql-test/suite/innodb/t/alter_candidate_key.test
index 7429cd89a1a..7c8f5e30993 100644
--- a/mysql-test/suite/innodb/t/alter_candidate_key.test
+++ b/mysql-test/suite/innodb/t/alter_candidate_key.test
@@ -24,6 +24,7 @@ CREATE TABLE t1(f1 INT, f2 INT,
PRIMARY KEY(f1, f2),
UNIQUE INDEX uidx2 (f1, f2),
UNIQUE INDEX uidx1 (f2))ENGINE=InnoDB;
+INSERT INTO t1 VALUES(2, 2);
ALTER TABLE t1 DROP PRIMARY KEY;
SHOW CREATE TABLE t1;
SET DEBUG_SYNC = 'innodb_inplace_alter_table_enter
@@ -42,6 +43,7 @@ DROP TABLE t1;
SET SQL_MODE= strict_trans_tables;
CREATE TABLE t1(a INT UNIQUE) ENGINE=InnoDB;
+INSERT INTO t1 VALUES(1);
SET DEBUG_SYNC='row_log_table_apply1_before SIGNAL dml WAIT_FOR dml_done';
--send ALTER TABLE t1 MODIFY COLUMN a INT NOT NULL
connection con1;
diff --git a/mysql-test/suite/innodb/t/alter_not_null_debug.test b/mysql-test/suite/innodb/t/alter_not_null_debug.test
index 7a965fd413a..9c5ba0faff0 100644
--- a/mysql-test/suite/innodb/t/alter_not_null_debug.test
+++ b/mysql-test/suite/innodb/t/alter_not_null_debug.test
@@ -75,7 +75,7 @@ SET DEBUG_SYNC='RESET';
--echo #
CREATE TABLE t1 (f VARCHAR(8) CHARACTER SET latin1 COLLATE latin1_swedish_ci)
ENGINE=InnoDB;
-
+INSERT INTO t1 VALUES('ZERO');
connection con1;
SET DEBUG_SYNC = 'row_log_table_apply1_before SIGNAL scanned WAIT_FOR insert_done';
send ALTER TABLE t1 MODIFY f VARCHAR(256) COLLATE latin1_german2_ci NOT NULL;
diff --git a/mysql-test/suite/innodb/t/alter_primary_key.test b/mysql-test/suite/innodb/t/alter_primary_key.test
index 4edc0cc023e..bf961c14b43 100644
--- a/mysql-test/suite/innodb/t/alter_primary_key.test
+++ b/mysql-test/suite/innodb/t/alter_primary_key.test
@@ -9,6 +9,7 @@
CREATE TABLE t0 (pk INT PRIMARY KEY) ENGINE=InnoDB;
CREATE TABLE t1 (c CHAR(2) NOT NULL) ENGINE=InnoDB;
+INSERT INTO t1 VALUES('cd');
connect (con1,localhost,root,,);
BEGIN;
diff --git a/mysql-test/suite/innodb/t/ddl_purge.test b/mysql-test/suite/innodb/t/ddl_purge.test
index 60d17acead8..e38b68c7bc9 100644
--- a/mysql-test/suite/innodb/t/ddl_purge.test
+++ b/mysql-test/suite/innodb/t/ddl_purge.test
@@ -4,6 +4,7 @@
CREATE TABLE t0 (pk INT PRIMARY KEY) ENGINE=InnoDB;
CREATE TABLE t1 (pk INT PRIMARY KEY, b INT) ENGINE=InnoDB;
+INSERT INTO t1 VALUES(100, 100);
--connect (con1,localhost,root,,test)
BEGIN;
diff --git a/mysql-test/suite/innodb/t/innodb-alter-tempfile.test b/mysql-test/suite/innodb/t/innodb-alter-tempfile.test
index cbf8ff9e87f..dac176f3b77 100644
--- a/mysql-test/suite/innodb/t/innodb-alter-tempfile.test
+++ b/mysql-test/suite/innodb/t/innodb-alter-tempfile.test
@@ -80,7 +80,7 @@ BEGIN;
DELETE FROM mysql.innodb_table_stats;
connect (con2,localhost,root,,);
-SET DEBUG_SYNC='inplace_after_index_build SIGNAL blocked WAIT_FOR ever';
+SET DEBUG_SYNC='innodb_inplace_alter_table_enter SIGNAL blocked WAIT_FOR ever';
send ALTER TABLE t1 FORCE;
connection default;
diff --git a/mysql-test/suite/innodb/t/innodb-index-debug.test b/mysql-test/suite/innodb/t/innodb-index-debug.test
index 2988a89c651..6e31200570b 100644
--- a/mysql-test/suite/innodb/t/innodb-index-debug.test
+++ b/mysql-test/suite/innodb/t/innodb-index-debug.test
@@ -96,6 +96,7 @@ drop table t1;
# Log file creation failure.
create table t1(k1 int auto_increment primary key,
k2 char(200),k3 char(200))engine=innodb;
+INSERT INTO t1 VALUES(1, "test", "test");
SET DEBUG_SYNC= 'row_merge_after_scan
SIGNAL opened WAIT_FOR flushed';
send ALTER TABLE t1 FORCE, ADD COLUMN k4 int;
@@ -122,6 +123,7 @@ drop table t480;
--echo #
CREATE TABLE t1 (j INT UNIQUE, i INT UNIQUE) ENGINE=InnoDB;
+INSERT INTO t1 VALUES(2, 2);
--connect (con1,localhost,root,,test)
SET DEBUG_SYNC='row_log_table_apply1_before SIGNAL built WAIT_FOR log';
--send
diff --git a/mysql-test/suite/innodb/t/innodb-index-online.test b/mysql-test/suite/innodb/t/innodb-index-online.test
index 5e21fa896a4..781ff8ee681 100644
--- a/mysql-test/suite/innodb/t/innodb-index-online.test
+++ b/mysql-test/suite/innodb/t/innodb-index-online.test
@@ -477,6 +477,7 @@ DROP TABLE t1;
--echo # MDEV-13205 assertion !dict_index_is_online_ddl(index) upon ALTER TABLE
--echo #
CREATE TABLE t1 (c VARCHAR(64)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES('foo');
SET DEBUG_SYNC = 'row_log_apply_before SIGNAL t1u_created WAIT_FOR dup_done';
send ALTER TABLE t1 ADD UNIQUE(c);
diff --git a/mysql-test/suite/innodb/t/instant_alter_debug.test b/mysql-test/suite/innodb/t/instant_alter_debug.test
index 10f7546cc36..8cf2610bbfb 100644
--- a/mysql-test/suite/innodb/t/instant_alter_debug.test
+++ b/mysql-test/suite/innodb/t/instant_alter_debug.test
@@ -186,6 +186,7 @@ connect stop_purge,localhost,root;
START TRANSACTION WITH CONSISTENT SNAPSHOT;
connect ddl,localhost,root,,test;
DELETE FROM t1;
+INSERT INTO t1 VALUES(1, 2);
SET DEBUG_SYNC='row_log_table_apply1_before SIGNAL copied WAIT_FOR logged';
send ALTER TABLE t1 FORCE;
connection default;
@@ -519,7 +520,7 @@ DROP TABLE t1;
CREATE TABLE t1
(a INT NOT NULL, b INT, c INT, d INT, e INT, f INT, g INT, h INT, i TEXT)
ENGINE=InnoDB;
-
+INSERT INTO t1 VALUES(1, 2, 3, 4, 5, 6, 7, 8, "test");
ALTER TABLE t1 MODIFY a INT NULL;
SET DEBUG_SYNC='innodb_inplace_alter_table_enter SIGNAL alter WAIT_FOR go';
diff --git a/mysql-test/suite/innodb_fts/r/misc_debug.result b/mysql-test/suite/innodb_fts/r/misc_debug.result
index 9f13822ecda..e252d7f6b11 100644
--- a/mysql-test/suite/innodb_fts/r/misc_debug.result
+++ b/mysql-test/suite/innodb_fts/r/misc_debug.result
@@ -30,6 +30,7 @@ DROP TABLE t2, t1;
# MDEV-25200 Index count mismatch due to aborted FULLTEXT INDEX
#
CREATE TABLE t1(a INT, b TEXT, c TEXT, FULLTEXT INDEX(b)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES(1, "test", "test_1");
connect con1,localhost,root,,test;
SET DEBUG_DBUG="+d,innodb_OOM_inplace_alter";
SET DEBUG_SYNC='innodb_commit_inplace_alter_table_enter SIGNAL s2 WAIT_FOR g2';
@@ -39,6 +40,7 @@ SET DEBUG_SYNC='now WAIT_FOR s2';
START TRANSACTION;
SELECT * FROM t1;
a b c
+1 test test_1
SET DEBUG_SYNC='now SIGNAL g2';
connection con1;
ERROR HY000: Out of memory.
diff --git a/mysql-test/suite/innodb_fts/t/misc_debug.test b/mysql-test/suite/innodb_fts/t/misc_debug.test
index c8542152d4d..4a0edf4ef88 100644
--- a/mysql-test/suite/innodb_fts/t/misc_debug.test
+++ b/mysql-test/suite/innodb_fts/t/misc_debug.test
@@ -59,6 +59,7 @@ DROP TABLE t2, t1;
--echo # MDEV-25200 Index count mismatch due to aborted FULLTEXT INDEX
--echo #
CREATE TABLE t1(a INT, b TEXT, c TEXT, FULLTEXT INDEX(b)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES(1, "test", "test_1");
connect(con1,localhost,root,,test);
SET DEBUG_DBUG="+d,innodb_OOM_inplace_alter";
SET DEBUG_SYNC='innodb_commit_inplace_alter_table_enter SIGNAL s2 WAIT_FOR g2';
diff --git a/sql/handler.h b/sql/handler.h
index 94ac56c3073..9b44b3fd297 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -2493,6 +2493,9 @@ public:
/** true when InnoDB should abort the alter when table is not empty */
bool error_if_not_empty;
+ /** True when DDL should avoid downgrading the MDL */
+ bool mdl_exclusive_after_prepare= false;
+
Alter_inplace_info(HA_CREATE_INFO *create_info_arg,
Alter_info *alter_info_arg,
KEY *key_info_arg, uint key_count_arg,
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index e46a13ce7a9..4409360cd8f 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -7709,15 +7709,16 @@ static bool mysql_inplace_alter_table(THD *thd,
lock for prepare phase under LOCK TABLES in the same way as when
exclusive lock is required for duration of the whole statement.
*/
- if (inplace_supported == HA_ALTER_INPLACE_EXCLUSIVE_LOCK ||
- ((inplace_supported == HA_ALTER_INPLACE_COPY_NO_LOCK ||
+ if (!ha_alter_info->mdl_exclusive_after_prepare &&
+ (inplace_supported == HA_ALTER_INPLACE_EXCLUSIVE_LOCK ||
+ ((inplace_supported == HA_ALTER_INPLACE_COPY_NO_LOCK ||
inplace_supported == HA_ALTER_INPLACE_COPY_LOCK ||
inplace_supported == HA_ALTER_INPLACE_NOCOPY_NO_LOCK ||
inplace_supported == HA_ALTER_INPLACE_NOCOPY_LOCK ||
inplace_supported == HA_ALTER_INPLACE_INSTANT) &&
(thd->locked_tables_mode == LTM_LOCK_TABLES ||
thd->locked_tables_mode == LTM_PRELOCKED_UNDER_LOCK_TABLES)) ||
- alter_info->requested_lock == Alter_info::ALTER_TABLE_LOCK_EXCLUSIVE)
+ alter_info->requested_lock == Alter_info::ALTER_TABLE_LOCK_EXCLUSIVE))
{
if (wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN))
goto cleanup;
diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc
index 7ee07f4160e..41871cedfe2 100644
--- a/storage/innobase/handler/handler0alter.cc
+++ b/storage/innobase/handler/handler0alter.cc
@@ -1949,10 +1949,15 @@ innobase_fts_check_doc_id_col(
}
/** Check whether the table is empty.
-@param[in] table table to be checked
+@param[in] table table to be checked
+@param[in] ignore_delete_marked Ignore the delete marked
+ flag record
@return true if table is empty */
-static bool innobase_table_is_empty(const dict_table_t *table)
+static bool innobase_table_is_empty(const dict_table_t *table,
+ bool ignore_delete_marked=true)
{
+ if (!table->space)
+ return false;
dict_index_t *clust_index= dict_table_get_first_index(table);
mtr_t mtr;
btr_pcur_t pcur;
@@ -1991,12 +1996,16 @@ next_page:
}
rec= page_cur_get_rec(cur);
- if (rec_get_deleted_flag(rec, dict_table_is_comp(table)));
- else if (!page_rec_is_supremum(rec))
+ if (rec_get_deleted_flag(rec, dict_table_is_comp(table)))
{
+ if (ignore_delete_marked)
+ goto scan_leaf;
+non_empty:
mtr.commit();
return false;
}
+ else if (!page_rec_is_supremum(rec))
+ goto non_empty;
else
{
next_page= true;
@@ -6853,6 +6862,7 @@ wrong_column_name:
DBUG_ASSERT(num_fts_index <= 1);
DBUG_ASSERT(!ctx->online || num_fts_index == 0);
DBUG_ASSERT(!ctx->online
+ || !ha_alter_info->mdl_exclusive_after_prepare
|| ctx->add_autoinc == ULINT_UNDEFINED);
DBUG_ASSERT(!ctx->online
|| !innobase_need_rebuild(ha_alter_info, old_table)
@@ -7666,6 +7676,20 @@ ha_innobase::prepare_inplace_alter_table(
DBUG_RETURN(false);
}
+#ifdef WITH_PARTITION_STORAGE_ENGINE
+ if (table->part_info == NULL) {
+#endif
+ /* Ignore the MDL downgrade when table is empty.
+ This optimization is disabled for partition table. */
+ ha_alter_info->mdl_exclusive_after_prepare =
+ innobase_table_is_empty(m_prebuilt->table, false);
+ if (ha_alter_info->online
+ && ha_alter_info->mdl_exclusive_after_prepare) {
+ ha_alter_info->online = false;
+ }
+#ifdef WITH_PARTITION_STORAGE_ENGINE
+ }
+#endif
indexed_table = m_prebuilt->table;
/* ALTER TABLE will not implicitly move a table from a single-table
@@ -8450,7 +8474,9 @@ ha_innobase::inplace_alter_table(
DEBUG_SYNC(m_user_thd, "innodb_inplace_alter_table_enter");
- if (!(ha_alter_info->handler_flags & INNOBASE_ALTER_DATA)) {
+ /* Ignore the inplace alter phase when table is empty */
+ if (!(ha_alter_info->handler_flags & INNOBASE_ALTER_DATA)
+ || ha_alter_info->mdl_exclusive_after_prepare) {
ok_exit:
DEBUG_SYNC(m_user_thd, "innodb_after_inplace_alter_table");
DBUG_RETURN(false);