Skip to content

Commit 2cf71b5

Browse files
committed
Bug#21644827 - FTS, ASSERT !SRV_READ_ONLY_MODE || M_IMPL.M_LOG_MODE == MTR_LOG_NO_REDO
Problem: -------- This bug and Bug#21691208 are because of incorrect table->flags2 value. For row_format=redundant, we dont read SYS_TABLES.MIX_LEN(flags2) because we think there could be garbage written before 3.23.52 version. Fix: ---- We now unconditionally read flags2 from SYS_TABLES and decide if it is garbage after evaluating if the tablespace is system tablespace, there are no fts indexes on the table and table is in redundant format Reviewed-by: Marko Makela <[email protected]> RB: 10288
1 parent a778250 commit 2cf71b5

File tree

3 files changed

+154
-23
lines changed

3 files changed

+154
-23
lines changed
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#
2+
# Bug#21644827 - FTS, ASSERT !SRV_READ_ONLY_MODE || M_IMPL.M_LOG_MODE ==
3+
# MTR_LOG_NO_REDO
4+
#
5+
create table t1 (a int not null, d varchar(15) not null, b
6+
varchar(198) not null, c char(156), primary key(b(3), a, d),
7+
fulltext ftsic(c)) engine=InnoDB
8+
row_format=redundant;
9+
insert into t1 values(123, 'abcdef', 'jghikl', 'mnop');
10+
insert into t1 values(456, 'abcdef', 'jghikl', 'mnop');
11+
insert into t1 values(789, 'abcdef', 'jghikl', 'mnop');
12+
SET GLOBAL innodb_file_per_table=OFF;
13+
create table t2 (a int not null, d varchar(15) not null, b
14+
varchar(198) not null, c char(156), primary key(b(3), a, d),
15+
fulltext ftsic(c)) engine=InnoDB
16+
row_format=redundant;
17+
insert into t2 select * from t1;
18+
create table t3 (a int not null, d varchar(15) not null, b varchar(198),
19+
c varchar(150), index k1(c(99), b(56)), index k2(b(5), c(10))) engine=InnoDB
20+
row_format=redundant;
21+
insert into t3 values(444, 'dddd', 'bbbbb', 'aaaaa');
22+
insert into t3 values(555, 'eeee', 'ccccc', 'aaaaa');
23+
SET GLOBAL innodb_fast_shutdown=0;
24+
# restart: --innodb-read-only
25+
SELECT * FROM t1;
26+
a d b c
27+
123 abcdef jghikl mnop
28+
456 abcdef jghikl mnop
29+
789 abcdef jghikl mnop
30+
SELECT * FROM t2;
31+
a d b c
32+
123 abcdef jghikl mnop
33+
456 abcdef jghikl mnop
34+
789 abcdef jghikl mnop
35+
SELECT * FROM t3;
36+
a d b c
37+
444 dddd bbbbb aaaaa
38+
555 eeee ccccc aaaaa
39+
# restart
40+
TRUNCATE TABLE t1;
41+
TRUNCATE TABLE t2;
42+
TRUNCATE TABLE t3;
43+
# restart: --debug=d,ib_table_invalid_flags
44+
SELECT * FROM t1;
45+
ERROR 42S02: Table 'test.t1' doesn't exist
46+
# restart
47+
DROP TABLE t1;
48+
DROP TABLE t2;
49+
DROP TABLE t3;
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
--source include/have_innodb.inc
2+
--source include/have_debug.inc
3+
# Embedded mode doesn't allow restarting
4+
--source include/not_embedded.inc
5+
6+
--echo #
7+
--echo # Bug#21644827 - FTS, ASSERT !SRV_READ_ONLY_MODE || M_IMPL.M_LOG_MODE ==
8+
--echo # MTR_LOG_NO_REDO
9+
--echo #
10+
11+
create table t1 (a int not null, d varchar(15) not null, b
12+
varchar(198) not null, c char(156), primary key(b(3), a, d),
13+
fulltext ftsic(c)) engine=InnoDB
14+
row_format=redundant;
15+
16+
insert into t1 values(123, 'abcdef', 'jghikl', 'mnop');
17+
insert into t1 values(456, 'abcdef', 'jghikl', 'mnop');
18+
insert into t1 values(789, 'abcdef', 'jghikl', 'mnop');
19+
20+
SET GLOBAL innodb_file_per_table=OFF;
21+
create table t2 (a int not null, d varchar(15) not null, b
22+
varchar(198) not null, c char(156), primary key(b(3), a, d),
23+
fulltext ftsic(c)) engine=InnoDB
24+
row_format=redundant;
25+
26+
insert into t2 select * from t1;
27+
28+
create table t3 (a int not null, d varchar(15) not null, b varchar(198),
29+
c varchar(150), index k1(c(99), b(56)), index k2(b(5), c(10))) engine=InnoDB
30+
row_format=redundant;
31+
32+
insert into t3 values(444, 'dddd', 'bbbbb', 'aaaaa');
33+
insert into t3 values(555, 'eeee', 'ccccc', 'aaaaa');
34+
35+
# read-only restart requires the change buffer to be empty; therefore we
36+
# do a slow shutdown.
37+
SET GLOBAL innodb_fast_shutdown=0;
38+
let $restart_parameters = restart: --innodb-read-only;
39+
--source include/restart_mysqld.inc
40+
41+
SELECT * FROM t1;
42+
SELECT * FROM t2;
43+
SELECT * FROM t3;
44+
45+
let $restart_parameters = restart;
46+
--source include/restart_mysqld.inc
47+
48+
TRUNCATE TABLE t1;
49+
TRUNCATE TABLE t2;
50+
TRUNCATE TABLE t3;
51+
52+
# These messages are relevant only when this debug parameter
53+
# "ib_table_invalid_flags" is enabled
54+
--disable_query_log
55+
call mtr.add_suppression("\\[ERROR\\] InnoDB: Table `test`.`t1` in InnoDB data dictionary contains invalid flags. SYS_TABLES.MIX_LEN=255");
56+
call mtr.add_suppression("\\[Warning\\] InnoDB: Parent table of FTS auxiliary table test/FTS_.* not found.");
57+
call mtr.add_suppression("\\[Warning\\] InnoDB: Cannot open table test/t1 from the internal data dictionary of InnoDB though the .frm file for the table exists.");
58+
--enable_query_log
59+
60+
let $restart_parameters = restart: --debug=d,ib_table_invalid_flags;
61+
--source include/restart_mysqld.inc
62+
63+
--error ER_NO_SUCH_TABLE
64+
SELECT * FROM t1;
65+
66+
let $restart_parameters = restart;
67+
--source include/restart_mysqld.inc
68+
69+
DROP TABLE t1;
70+
DROP TABLE t2;
71+
DROP TABLE t3;

storage/innobase/dict/dict0load.cc

Lines changed: 34 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1309,31 +1309,16 @@ dict_sys_tables_rec_read(
13091309

13101310
*flags = dict_sys_tables_type_to_tf(type, *n_cols);
13111311

1312-
/* For tables created with old versions of InnoDB, there may be
1313-
garbage in SYS_TABLES.MIX_LEN where flags2 are found. Such tables
1314-
would always be in ROW_FORMAT=REDUNDANT which do not have the
1315-
high bit set in n_cols, and flags would be zero. */
1316-
if (*flags != 0 || *n_cols & DICT_N_COLS_COMPACT) {
1317-
1318-
/* Get flags2 from SYS_TABLES.MIX_LEN */
1319-
field = rec_get_nth_field_old(
1320-
rec, DICT_FLD__SYS_TABLES__MIX_LEN, &len);
1321-
*flags2 = mach_read_from_4(field);
1322-
1323-
if (!dict_tf2_is_valid(*flags, *flags2)) {
1324-
ib::error() << "Table " << table_name << " in InnoDB"
1325-
" data dictionary contains invalid flags."
1326-
" SYS_TABLES.MIX_LEN=" << *flags2;
1327-
*flags2 = ULINT_UNDEFINED;
1328-
return(false);
1329-
}
1312+
/* Get flags2 from SYS_TABLES.MIX_LEN */
1313+
field = rec_get_nth_field_old(
1314+
rec, DICT_FLD__SYS_TABLES__MIX_LEN, &len);
1315+
*flags2 = mach_read_from_4(field);
13301316

1331-
/* DICT_TF2_FTS will be set when indexes are being loaded */
1332-
*flags2 &= ~DICT_TF2_FTS;
1317+
/* DICT_TF2_FTS will be set when indexes are being loaded */
1318+
*flags2 &= ~DICT_TF2_FTS;
13331319

1334-
/* Now that we have used this bit, unset it. */
1335-
*n_cols &= ~DICT_N_COLS_COMPACT;
1336-
}
1320+
/* Now that we have used this bit, unset it. */
1321+
*n_cols &= ~DICT_N_COLS_COMPACT;
13371322

13381323
return(true);
13391324
}
@@ -3163,6 +3148,32 @@ dict_load_table_one(
31633148
}
31643149
}
31653150

3151+
/* We don't trust the table->flags2(retrieved from SYS_TABLES.MIX_LEN
3152+
field) if the datafiles are from 3.23.52 version. To identify this
3153+
version, we do the below check and reset the flags. */
3154+
if (!DICT_TF2_FLAG_IS_SET(table, DICT_TF2_FTS_HAS_DOC_ID)
3155+
&& table->space == srv_sys_space.space_id()
3156+
&& table->flags == 0) {
3157+
table->flags2 = 0;
3158+
}
3159+
3160+
DBUG_EXECUTE_IF("ib_table_invalid_flags",
3161+
if(strcmp(table->name.m_name, "test/t1") == 0) {
3162+
table->flags2 = 255;
3163+
table->flags = 255;
3164+
});
3165+
3166+
if (!dict_tf2_is_valid(table->flags, table->flags2)) {
3167+
ib::error() << "Table " << table->name << " in InnoDB"
3168+
" data dictionary contains invalid flags."
3169+
" SYS_TABLES.MIX_LEN=" << table->flags2;
3170+
table->flags2 &= ~(DICT_TF2_TEMPORARY|DICT_TF2_INTRINSIC);
3171+
dict_table_remove_from_cache(table);
3172+
table = NULL;
3173+
err = DB_FAIL;
3174+
goto func_exit;
3175+
}
3176+
31663177
/* Initialize table foreign_child value. Its value could be
31673178
changed when dict_load_foreigns() is called below */
31683179
table->fk_max_recusive_level = 0;

0 commit comments

Comments
 (0)