Skip to content

Commit a0bc9d8

Browse files
author
Darshan M N
committed
Bug#21514135 SCHEMA MISMATCH ERROR WHEN IMPORTING TABLESPACE AFTER DROPPING
AN INDEX Problem: ======== A schema mismatch error occurs when importing a TABLESPACE from one server to another. The situation occurs when importing a table has been altered by DROP INDEX on the source server. The high level flow is: 1) Drop an index from a table on the source server 2) Move the table to the destination server using transportable TABLESPACES 3) Receive a "SCHEMA MISMATCH" error when importing TABLESPACE This problem is due to the variable dict_col_t->ord_part of a column, part of an index to be dropped, not being reset to 0. Fix: ==== During the dropping of an index, it is checked if the column being part of the index to be dropped is part of any other index which is not being dropped. If it is not part of any other index then the dict_col_t->ord_part variable is reset to 0. Reviewed-by: Jimmy Yang <[email protected]> Reviewed-by: Satya Bodapati <[email protected]> RB: 10212
1 parent 2db4b0f commit a0bc9d8

File tree

5 files changed

+211
-22
lines changed

5 files changed

+211
-22
lines changed

mysql-test/suite/innodb/include/import.inc

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,38 @@
33

44
let $MYSQLD_DATADIR = `SELECT @@datadir`;
55

6-
FLUSH TABLES t1 FOR EXPORT;
6+
if(!$source_db) {
7+
let $source_db = test;
8+
}
79

8-
--copy_file $MYSQLD_DATADIR/test/t1.cfg $MYSQLD_DATADIR/t1.cfg_back
9-
--copy_file $MYSQLD_DATADIR/test/t1.ibd $MYSQLD_DATADIR/t1.ibd_back
10+
if(!$dest_db) {
11+
let $dest_db = test;
12+
}
13+
14+
eval FLUSH TABLES $source_db.t1 FOR EXPORT;
15+
16+
--copy_file $MYSQLD_DATADIR/$source_db/t1.cfg $MYSQLD_DATADIR/t1.cfg_back
17+
--copy_file $MYSQLD_DATADIR/$source_db/t1.ibd $MYSQLD_DATADIR/t1.ibd_back
1018

1119
UNLOCK TABLES;
12-
ALTER TABLE t1 DISCARD TABLESPACE;
1320

14-
--move_file $MYSQLD_DATADIR/t1.cfg_back $MYSQLD_DATADIR/test/t1.cfg
15-
--move_file $MYSQLD_DATADIR/t1.ibd_back $MYSQLD_DATADIR/test/t1.ibd
21+
if($source_db != $dest_db) {
22+
eval USE $dest_db;
23+
let $create1 = query_get_value(SHOW CREATE TABLE $source_db.t1, Create Table, 1);
24+
eval $create1;
25+
}
26+
27+
eval ALTER TABLE $dest_db.t1 DISCARD TABLESPACE;
28+
29+
--move_file $MYSQLD_DATADIR/t1.cfg_back $MYSQLD_DATADIR/$dest_db/t1.cfg
30+
--move_file $MYSQLD_DATADIR/t1.ibd_back $MYSQLD_DATADIR/$dest_db/t1.ibd
31+
32+
eval ALTER TABLE $dest_db.t1 IMPORT TABLESPACE;
1633

17-
ALTER TABLE t1 IMPORT TABLESPACE;
34+
eval CHECK TABLE $dest_db.t1;
35+
eval SHOW CREATE TABLE $dest_db.t1;
36+
eval SELECT * FROM $dest_db.t1;
1837

19-
CHECK TABLE t1;
20-
SHOW CREATE TABLE t1;
21-
SELECT * FROM t1;
38+
if($source_db != $dest_db) {
39+
eval DROP TABLE $dest_db.t1;
40+
}

mysql-test/suite/innodb/r/import.result

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@ ALTER TABLE t1 ADD INDEX ind2(c3, c1(10), c2);
99
ALTER TABLE t1 ADD INDEX ind3(c2, c3, c1(20));
1010
INSERT INTO t1 VALUES ('Test Data -1', 'Test Data -2', 'Test Data -3');
1111
# Test with 2ndary index having prefix
12-
FLUSH TABLES t1 FOR EXPORT;
12+
FLUSH TABLES test.t1 FOR EXPORT;
1313
UNLOCK TABLES;
14-
ALTER TABLE t1 DISCARD TABLESPACE;
15-
ALTER TABLE t1 IMPORT TABLESPACE;
16-
CHECK TABLE t1;
14+
ALTER TABLE test.t1 DISCARD TABLESPACE;
15+
ALTER TABLE test.t1 IMPORT TABLESPACE;
16+
CHECK TABLE test.t1;
1717
Table Op Msg_type Msg_text
1818
test.t1 check status OK
19-
SHOW CREATE TABLE t1;
19+
SHOW CREATE TABLE test.t1;
2020
Table Create Table
2121
t1 CREATE TABLE `t1` (
2222
`c1` varchar(32) NOT NULL DEFAULT '',
@@ -27,19 +27,19 @@ t1 CREATE TABLE `t1` (
2727
KEY `ind2` (`c3`,`c1`(10),`c2`),
2828
KEY `ind3` (`c2`,`c3`,`c1`(20))
2929
) ENGINE=InnoDB DEFAULT CHARSET=latin1
30-
SELECT * FROM t1;
30+
SELECT * FROM test.t1;
3131
c1 c2 c3
3232
Test Data -1 Test Data -2 Test Data -3
3333
# Test with PK & 2ndary index with prefix
3434
ALTER TABLE t1 DROP PRIMARY KEY, ADD PRIMARY KEY(c1(5), c2(10), c3(20));
35-
FLUSH TABLES t1 FOR EXPORT;
35+
FLUSH TABLES test.t1 FOR EXPORT;
3636
UNLOCK TABLES;
37-
ALTER TABLE t1 DISCARD TABLESPACE;
38-
ALTER TABLE t1 IMPORT TABLESPACE;
39-
CHECK TABLE t1;
37+
ALTER TABLE test.t1 DISCARD TABLESPACE;
38+
ALTER TABLE test.t1 IMPORT TABLESPACE;
39+
CHECK TABLE test.t1;
4040
Table Op Msg_type Msg_text
4141
test.t1 check status OK
42-
SHOW CREATE TABLE t1;
42+
SHOW CREATE TABLE test.t1;
4343
Table Create Table
4444
t1 CREATE TABLE `t1` (
4545
`c1` varchar(32) NOT NULL DEFAULT '',
@@ -50,7 +50,7 @@ t1 CREATE TABLE `t1` (
5050
KEY `ind2` (`c3`,`c1`(10),`c2`),
5151
KEY `ind3` (`c2`,`c3`,`c1`(20))
5252
) ENGINE=InnoDB DEFAULT CHARSET=latin1
53-
SELECT * FROM t1;
53+
SELECT * FROM test.t1;
5454
c1 c2 c3
5555
Test Data -1 Test Data -2 Test Data -3
5656
DROP TABLE t1;

mysql-test/suite/innodb/r/innodb-alter.result

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -790,3 +790,73 @@ CHECK TABLE t1;
790790
Table Op Msg_type Msg_text
791791
test.t1 check status OK
792792
DROP TABLE t1, parent;
793+
#
794+
#BUG#21514135 SCHEMA MISMATCH ERROR WHEN IMPORTING TABLESPACE AFTER
795+
#DROPPING AN INDEX
796+
#
797+
CREATE DATABASE source_db;
798+
CREATE DATABASE dest_db;
799+
CREATE TABLE source_db.t1 (
800+
id int(11) NOT NULL,
801+
age int(11) DEFAULT NULL,
802+
name varchar(20),
803+
PRIMARY KEY (id),
804+
KEY index1 (age)
805+
) ENGINE=InnoDB;
806+
ALTER TABLE source_db.t1 DROP INDEX index1, ADD INDEX index2(name, age), algorithm=inplace;
807+
FLUSH TABLES source_db.t1 FOR EXPORT;
808+
UNLOCK TABLES;
809+
USE dest_db;
810+
CREATE TABLE `t1` (
811+
`id` int(11) NOT NULL,
812+
`age` int(11) DEFAULT NULL,
813+
`name` varchar(20) DEFAULT NULL,
814+
PRIMARY KEY (`id`),
815+
KEY `index2` (`name`,`age`)
816+
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
817+
ALTER TABLE dest_db.t1 DISCARD TABLESPACE;
818+
ALTER TABLE dest_db.t1 IMPORT TABLESPACE;
819+
CHECK TABLE dest_db.t1;
820+
Table Op Msg_type Msg_text
821+
dest_db.t1 check status OK
822+
SHOW CREATE TABLE dest_db.t1;
823+
Table Create Table
824+
t1 CREATE TABLE `t1` (
825+
`id` int(11) NOT NULL,
826+
`age` int(11) DEFAULT NULL,
827+
`name` varchar(20) DEFAULT NULL,
828+
PRIMARY KEY (`id`),
829+
KEY `index2` (`name`,`age`)
830+
) ENGINE=InnoDB DEFAULT CHARSET=latin1
831+
SELECT * FROM dest_db.t1;
832+
id age name
833+
DROP TABLE dest_db.t1;
834+
ALTER TABLE source_db.t1 DROP INDEX index2, algorithm=inplace;
835+
FLUSH TABLES source_db.t1 FOR EXPORT;
836+
UNLOCK TABLES;
837+
USE dest_db;
838+
CREATE TABLE `t1` (
839+
`id` int(11) NOT NULL,
840+
`age` int(11) DEFAULT NULL,
841+
`name` varchar(20) DEFAULT NULL,
842+
PRIMARY KEY (`id`)
843+
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
844+
ALTER TABLE dest_db.t1 DISCARD TABLESPACE;
845+
ALTER TABLE dest_db.t1 IMPORT TABLESPACE;
846+
CHECK TABLE dest_db.t1;
847+
Table Op Msg_type Msg_text
848+
dest_db.t1 check status OK
849+
SHOW CREATE TABLE dest_db.t1;
850+
Table Create Table
851+
t1 CREATE TABLE `t1` (
852+
`id` int(11) NOT NULL,
853+
`age` int(11) DEFAULT NULL,
854+
`name` varchar(20) DEFAULT NULL,
855+
PRIMARY KEY (`id`)
856+
) ENGINE=InnoDB DEFAULT CHARSET=latin1
857+
SELECT * FROM dest_db.t1;
858+
id age name
859+
DROP TABLE dest_db.t1;
860+
DROP TABLE source_db.t1;
861+
DROP DATABASE source_db;
862+
DROP DATABASE dest_db;

mysql-test/suite/innodb/t/innodb-alter.test

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,3 +449,33 @@ SHOW CREATE TABLE t1;
449449
CHECK TABLE t1;
450450

451451
DROP TABLE t1, parent;
452+
453+
--echo #
454+
--echo #BUG#21514135 SCHEMA MISMATCH ERROR WHEN IMPORTING TABLESPACE AFTER
455+
--echo #DROPPING AN INDEX
456+
--echo #
457+
let $source_db = source_db;
458+
let $dest_db = dest_db;
459+
460+
eval CREATE DATABASE $source_db;
461+
eval CREATE DATABASE $dest_db;
462+
463+
eval CREATE TABLE $source_db.t1 (
464+
id int(11) NOT NULL,
465+
age int(11) DEFAULT NULL,
466+
name varchar(20),
467+
PRIMARY KEY (id),
468+
KEY index1 (age)
469+
) ENGINE=InnoDB;
470+
471+
eval ALTER TABLE $source_db.t1 DROP INDEX index1, ADD INDEX index2(name, age), algorithm=inplace;
472+
473+
--source suite/innodb/include/import.inc
474+
475+
eval ALTER TABLE $source_db.t1 DROP INDEX index2, algorithm=inplace;
476+
477+
--source suite/innodb/include/import.inc
478+
479+
eval DROP TABLE $source_db.t1;
480+
eval DROP DATABASE $source_db;
481+
eval DROP DATABASE $dest_db;

storage/innobase/handler/handler0alter.cc

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5026,6 +5026,61 @@ commit_cache_rebuild(
50265026
DBUG_VOID_RETURN;
50275027
}
50285028

5029+
/** Store the column number of the columns in a list belonging
5030+
to indexes which are not being dropped.
5031+
@param[in] ctx In-place ALTER TABLE context
5032+
@param[in, out] drop_col_list list which will be set, containing columns
5033+
which is part of index being dropped */
5034+
static
5035+
void
5036+
get_col_list_to_be_dropped(
5037+
ha_innobase_inplace_ctx* ctx,
5038+
std::set<ulint>& drop_col_list)
5039+
{
5040+
for (ulint index_count = 0; index_count < ctx->num_to_drop_index;
5041+
index_count++) {
5042+
dict_index_t* index = ctx->drop_index[index_count];
5043+
5044+
for (ulint col = 0; col < index->n_user_defined_cols; col++) {
5045+
ulint col_no = dict_index_get_nth_col_no(index, col);
5046+
drop_col_list.insert(col_no);
5047+
}
5048+
}
5049+
}
5050+
5051+
/** For each column, which is part of an index which is not going to be
5052+
dropped, it checks if the column number of the column is same as col_no
5053+
argument passed.
5054+
@param[in] table table object
5055+
@param[in] col_no column number of the column which is to be checked
5056+
@retval true column exists
5057+
@retval false column does not exist. */
5058+
static
5059+
bool
5060+
check_col_exists_in_indexes(
5061+
const dict_table_t* table,
5062+
ulint col_no)
5063+
{
5064+
for (dict_index_t* index = dict_table_get_first_index(table); index;
5065+
index = dict_table_get_next_index(index)) {
5066+
5067+
if (index->to_be_dropped) {
5068+
continue;
5069+
}
5070+
5071+
for (ulint col = 0; col < index->n_user_defined_cols; col++) {
5072+
5073+
ulint index_col_no = dict_index_get_nth_col_no(
5074+
index, col);
5075+
if (col_no == index_col_no) {
5076+
return(true);
5077+
}
5078+
}
5079+
}
5080+
5081+
return(false);
5082+
}
5083+
50295084
/** Commit the changes made during prepare_inplace_alter_table()
50305085
and inplace_alter_table() inside the data dictionary tables,
50315086
when not rebuilding the table.
@@ -5056,6 +5111,21 @@ commit_try_norebuild(
50565111
DBUG_ASSERT(ctx->num_to_drop_fk
50575112
== ha_alter_info->alter_info->drop_list.elements);
50585113

5114+
5115+
std::set<ulint> drop_list;
5116+
std::set<ulint>::iterator col_no;
5117+
5118+
/* Check if the column, part of an index to be dropped is part of any
5119+
other index which is not being dropped. If it so, then set the ord_part
5120+
of the column to 0. */
5121+
get_col_list_to_be_dropped(ctx, drop_list);
5122+
5123+
for(col_no = drop_list.begin(); col_no != drop_list.end(); ++col_no) {
5124+
if (!check_col_exists_in_indexes(ctx->new_table, *col_no)) {
5125+
ctx->new_table->cols[*col_no].ord_part = 0;
5126+
}
5127+
}
5128+
50595129
for (ulint i = 0; i < ctx->num_to_add_index; i++) {
50605130
dict_index_t* index = ctx->add_index[i];
50615131
DBUG_ASSERT(dict_index_get_online_status(index)

0 commit comments

Comments
 (0)