Skip to content
/ server Public

Commit 6a2afb4

Browse files
MDEV-36487 Fix ha_innobase::check() for sequences
InnoDB does the following check for sequence table during check table command: - There should be only one index should exist on sequence table - There should be only one row should exist on sequence table - The leaf page must be the root page for the sequence table - Delete marked record should not exist - DB_TRX_ID and DB_ROLL_PTR of the record should be 0 and 1U << 55
1 parent 37274ae commit 6a2afb4

File tree

6 files changed

+395
-3
lines changed

6 files changed

+395
-3
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
--- check_sequence.result
2+
+++ check_sequence,debug.result
3+
@@ -112,3 +112,14 @@
4+
3
5+
disconnect prevent_purge;
6+
DROP SEQUENCE s1;
7+
+CREATE SEQUENCE s ENGINE=InnoDB;
8+
+ALTER TABLE s SEQUENCE=0;
9+
+FLUSH TABLES;
10+
+SET STATEMENT DEBUG_DBUG="+d,fail_root_page" FOR
11+
+CHECK TABLE s;
12+
+Table Op Msg_type Msg_text
13+
+test.s check Warning InnoDB: Sequence table test/s is corrupted.
14+
+test.s check error Corrupt
15+
+ALTER TABLE s SEQUENCE=1;
16+
+ERROR HY000: InnoDB: Table `test`.`s` is corrupted.
17+
+DROP SEQUENCE s;
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
#
2+
# MDEV-36487 Fix ha_innobase::check() for sequences
3+
#
4+
call mtr.add_suppression("InnoDB: Table test/s2 contains 1 indexes .*");
5+
call mtr.add_suppression("Table test/s2 has a primary key in InnoDB .*");
6+
CREATE SEQUENCE s ENGINE=InnoDB;
7+
ALTER TABLE s SEQUENCE=0, ALGORITHM=INPLACE;
8+
ERROR 0A000: ALGORITHM=INPLACE is not supported. Reason: SEQUENCE. Try ALGORITHM=COPY
9+
ALTER TABLE s SEQUENCE=0, ALGORITHM=COPY;
10+
FLUSH TABLES;
11+
CHECK TABLE s;
12+
Table Op Msg_type Msg_text
13+
test.s check Warning InnoDB: Sequence table test/s has ROLLBACK enabled.
14+
test.s check error Corrupt
15+
ALTER TABLE s SEQUENCE=1;
16+
ERROR HY000: InnoDB: Table `test`.`s` is corrupted.
17+
DROP SEQUENCE s;
18+
CREATE SEQUENCE s ENGINE=InnoDB;
19+
CREATE TABLE s2 LIKE s;
20+
ALTER TABLE s2 sequence=0;
21+
INSERT INTO s2 VALUES (3,1,9223372036854775806,1,1,1000,0,0);
22+
ALTER TABLE s2 ADD INDEX idx(start_value);
23+
FLUSH TABLES;
24+
CHECK TABLE s2;
25+
Table Op Msg_type Msg_text
26+
test.s2 check Warning InnoDB: Table test/s2 contains 1 indexes inside InnoDB, which is different from the number of indexes 0 defined in the MariaDB
27+
test.s2 check Warning InnoDB: Sequence table test/s2 does have more than one indexes.
28+
test.s2 check error Corrupt
29+
ALTER TABLE s2 SEQUENCE=1;
30+
ERROR HY000: InnoDB: Table `test`.`s2` is corrupted.
31+
DROP SEQUENCE s;
32+
DROP SEQUENCE s2;
33+
CREATE SEQUENCE s ENGINE=InnoDB;
34+
CREATE TABLE s2 LIKE s;
35+
ALTER TABLE s2 sequence=0;
36+
INSERT INTO s2 VALUES (3,2,9223372036854775806,2,2,1000,0,0);
37+
ALTER TABLE s2 ADD PRIMARY KEY(start_value);
38+
FLUSH TABLES;
39+
CHECK TABLE s2;
40+
Table Op Msg_type Msg_text
41+
test.s2 check Warning InnoDB: Table test/s2 has a primary key in InnoDB data dictionary, but not in MariaDB!
42+
test.s2 check Warning InnoDB: Table test/s2 contains 1 indexes inside InnoDB, which is different from the number of indexes 0 defined in the MariaDB
43+
test.s2 check Warning InnoDB: Sequence table test/s2 does not have generated clustered index.
44+
test.s2 check error Corrupt
45+
ALTER TABLE s2 SEQUENCE=1;
46+
ERROR HY000: InnoDB: Table `test`.`s2` is corrupted.
47+
DROP SEQUENCE s;
48+
DROP SEQUENCE s2;
49+
CREATE SEQUENCE s ENGINE=InnoDB;
50+
CREATE TABLE s2 LIKE s;
51+
ALTER TABLE s2 sequence=0;
52+
INSERT INTO s2 VALUES (3,1,9223372036854775806,1,1,1000,0,0);
53+
DELETE FROM s2;
54+
InnoDB 0 transactions not purged
55+
FLUSH TABLES;
56+
CHECK TABLE s2;
57+
Table Op Msg_type Msg_text
58+
test.s2 check Warning InnoDB: Should have only one record in sequence table test/s2. But it has 0 records.
59+
test.s2 check error Corrupt
60+
ALTER TABLE s2 SEQUENCE=1;
61+
ERROR HY000: InnoDB: Table `test`.`s2` is corrupted.
62+
DROP SEQUENCE s;
63+
DROP SEQUENCE s2;
64+
CREATE SEQUENCE s ENGINE=InnoDB;
65+
CREATE TABLE s2 LIKE s;
66+
ALTER TABLE s2 sequence=0;
67+
INSERT INTO s2 select seq, seq, seq, seq, seq, seq, 1, seq from
68+
seq_1_to_200;
69+
FLUSH TABLES;
70+
CHECK TABLE s2;
71+
Table Op Msg_type Msg_text
72+
test.s2 check Warning InnoDB: Non leaf page exists for sequence table test/s2.
73+
test.s2 check error Corrupt
74+
ALTER TABLE s2 SEQUENCE=1;
75+
ERROR HY000: InnoDB: Table `test`.`s2` is corrupted.
76+
DROP SEQUENCE s;
77+
DROP SEQUENCE s2;
78+
CREATE SEQUENCE s ENGINE=InnoDB;
79+
CREATE TABLE s2 LIKE s;
80+
ALTER TABLE s2 sequence=0;
81+
DELETE FROM s2;
82+
InnoDB 0 transactions not purged
83+
connect prevent_purge,localhost,root;
84+
START TRANSACTION WITH CONSISTENT SNAPSHOT;
85+
connection default;
86+
INSERT INTO s2 VALUES (3,1,9223372036854775806,1,1,1000,0,0);
87+
FLUSH TABLES;
88+
CHECK TABLE s2;
89+
Table Op Msg_type Msg_text
90+
test.s2 check Warning InnoDB: Record in sequence table test/s2 is corrupted.
91+
test.s2 check error Corrupt
92+
ALTER TABLE s2 SEQUENCE=1;
93+
ERROR HY000: InnoDB: Table `test`.`s2` is corrupted.
94+
DROP SEQUENCE s;
95+
DROP SEQUENCE s2;
96+
CREATE SEQUENCE s1 ENGINE=InnoDB;
97+
CHECK TABLE s1;
98+
Table Op Msg_type Msg_text
99+
test.s1 check status OK
100+
connection prevent_purge;
101+
START TRANSACTION WITH CONSISTENT SNAPSHOT;
102+
connection default;
103+
INSERT INTO s1 VALUES (3,1,9223372036854775806,1,1,1000,0,0);
104+
SELECT * FROM s1;
105+
next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
106+
3 1 9223372036854775806 1 1 1000 0 0
107+
CHECK TABLE s1;
108+
Table Op Msg_type Msg_text
109+
test.s1 check status OK
110+
select nextval(s1);
111+
nextval(s1)
112+
3
113+
disconnect prevent_purge;
114+
DROP SEQUENCE s1;
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
--source include/have_innodb.inc
2+
--source include/have_sequence.inc
3+
--source include/maybe_debug.inc
4+
--echo #
5+
--echo # MDEV-36487 Fix ha_innobase::check() for sequences
6+
--echo #
7+
8+
call mtr.add_suppression("InnoDB: Table test/s2 contains 1 indexes .*");
9+
call mtr.add_suppression("Table test/s2 has a primary key in InnoDB .*");
10+
# Sequence table which has NO_ROLLBACK flag set
11+
let $datadir=`select @@datadir`;
12+
CREATE SEQUENCE s ENGINE=InnoDB;
13+
copy_file $datadir/test/s.frm $datadir/test/s1.frm;
14+
--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
15+
ALTER TABLE s SEQUENCE=0, ALGORITHM=INPLACE;
16+
ALTER TABLE s SEQUENCE=0, ALGORITHM=COPY;
17+
FLUSH TABLES;
18+
remove_file $datadir/test/s.frm;
19+
move_file $datadir/test/s1.frm $datadir/test/s.frm;
20+
CHECK TABLE s;
21+
--error ER_TABLE_CORRUPT
22+
ALTER TABLE s SEQUENCE=1;
23+
DROP SEQUENCE s;
24+
25+
# Checks for more than one index
26+
CREATE SEQUENCE s ENGINE=InnoDB;
27+
copy_file $datadir/test/s.frm $datadir/test/orig.frm;
28+
CREATE TABLE s2 LIKE s;
29+
ALTER TABLE s2 sequence=0;
30+
INSERT INTO s2 VALUES (3,1,9223372036854775806,1,1,1000,0,0);
31+
ALTER TABLE s2 ADD INDEX idx(start_value);
32+
FLUSH TABLES;
33+
move_file $datadir/test/orig.frm $datadir/test/s2.frm;
34+
CHECK TABLE s2;
35+
--error ER_TABLE_CORRUPT
36+
ALTER TABLE s2 SEQUENCE=1;
37+
DROP SEQUENCE s;
38+
DROP SEQUENCE s2;
39+
40+
# Checks for generated clustered index
41+
CREATE SEQUENCE s ENGINE=InnoDB;
42+
copy_file $datadir/test/s.frm $datadir/test/orig.frm;
43+
CREATE TABLE s2 LIKE s;
44+
ALTER TABLE s2 sequence=0;
45+
INSERT INTO s2 VALUES (3,2,9223372036854775806,2,2,1000,0,0);
46+
ALTER TABLE s2 ADD PRIMARY KEY(start_value);
47+
FLUSH TABLES;
48+
move_file $datadir/test/orig.frm $datadir/test/s2.frm;
49+
CHECK TABLE s2;
50+
--error ER_TABLE_CORRUPT
51+
ALTER TABLE s2 SEQUENCE=1;
52+
DROP SEQUENCE s;
53+
DROP SEQUENCE s2;
54+
55+
# Should contain only one record
56+
CREATE SEQUENCE s ENGINE=InnoDB;
57+
copy_file $datadir/test/s.frm $datadir/test/orig.frm;
58+
CREATE TABLE s2 LIKE s;
59+
ALTER TABLE s2 sequence=0;
60+
INSERT INTO s2 VALUES (3,1,9223372036854775806,1,1,1000,0,0);
61+
DELETE FROM s2;
62+
--source include/wait_all_purged.inc
63+
FLUSH TABLES;
64+
move_file $datadir/test/orig.frm $datadir/test/s2.frm;
65+
CHECK TABLE s2;
66+
--error ER_TABLE_CORRUPT
67+
ALTER TABLE s2 SEQUENCE=1;
68+
DROP SEQUENCE s;
69+
DROP SEQUENCE s2;
70+
71+
# More than one page
72+
CREATE SEQUENCE s ENGINE=InnoDB;
73+
copy_file $datadir/test/s.frm $datadir/test/orig.frm;
74+
CREATE TABLE s2 LIKE s;
75+
ALTER TABLE s2 sequence=0;
76+
INSERT INTO s2 select seq, seq, seq, seq, seq, seq, 1, seq from
77+
seq_1_to_200;
78+
FLUSH TABLES;
79+
move_file $datadir/test/orig.frm $datadir/test/s2.frm;
80+
CHECK TABLE s2;
81+
--error ER_TABLE_CORRUPT
82+
ALTER TABLE s2 SEQUENCE=1;
83+
DROP SEQUENCE s;
84+
DROP SEQUENCE s2;
85+
86+
# Checks for DB_TRX_ID & DB_ROLL_PTR in the record
87+
CREATE SEQUENCE s ENGINE=InnoDB;
88+
copy_file $datadir/test/s.frm $datadir/test/orig.frm;
89+
CREATE TABLE s2 LIKE s;
90+
ALTER TABLE s2 sequence=0;
91+
DELETE FROM s2;
92+
--source include/wait_all_purged.inc
93+
--connect (prevent_purge,localhost,root)
94+
START TRANSACTION WITH CONSISTENT SNAPSHOT;
95+
--connection default
96+
INSERT INTO s2 VALUES (3,1,9223372036854775806,1,1,1000,0,0);
97+
FLUSH TABLES;
98+
move_file $datadir/test/orig.frm $datadir/test/s2.frm;
99+
CHECK TABLE s2;
100+
--error ER_TABLE_CORRUPT
101+
ALTER TABLE s2 SEQUENCE=1;
102+
DROP SEQUENCE s;
103+
DROP SEQUENCE s2;
104+
105+
# Insert a row into a sequence table updates that row
106+
CREATE SEQUENCE s1 ENGINE=InnoDB;
107+
CHECK TABLE s1;
108+
109+
--connection prevent_purge
110+
START TRANSACTION WITH CONSISTENT SNAPSHOT;
111+
112+
--connection default
113+
INSERT INTO s1 VALUES (3,1,9223372036854775806,1,1,1000,0,0);
114+
SELECT * FROM s1;
115+
CHECK TABLE s1;
116+
--disable_ps2_protocol
117+
select nextval(s1);
118+
--enable_ps2_protocol
119+
--disconnect prevent_purge
120+
DROP SEQUENCE s1;
121+
122+
if ($have_debug)
123+
{
124+
# Root page is corrupted
125+
CREATE SEQUENCE s ENGINE=InnoDB;
126+
copy_file $datadir/test/s.frm $datadir/test/s1.frm;
127+
ALTER TABLE s SEQUENCE=0;
128+
FLUSH TABLES;
129+
remove_file $datadir/test/s.frm;
130+
move_file $datadir/test/s1.frm $datadir/test/s.frm;
131+
SET STATEMENT DEBUG_DBUG="+d,fail_root_page" FOR
132+
CHECK TABLE s;
133+
--error ER_TABLE_CORRUPT
134+
ALTER TABLE s SEQUENCE=1;
135+
DROP SEQUENCE s;
136+
}

mysql-test/suite/sql_sequence/check.result

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -120,12 +120,16 @@ drop sequence s;
120120
#
121121
CREATE SEQUENCE s engine=innodb;
122122
ALTER TABLE s sequence=0;
123+
connect prevent_purge,localhost,root;
124+
START TRANSACTION WITH CONSISTENT SNAPSHOT;
125+
connection default;
123126
delete from s;
124127
FLUSH TABLES;
125128
CHECK TABLE s;
126129
Table Op Msg_type Msg_text
127-
test.s check Error Fewer than one row in the table
130+
test.s check Warning InnoDB: Encountered delete marked record in sequence table test/s.
128131
test.s check error Corrupt
132+
disconnect prevent_purge;
129133
DROP SEQUENCE s;
130134
CREATE SEQUENCE s engine=innodb;
131135
CHECK TABLE s;
@@ -138,6 +142,6 @@ insert into s values (2,1,9223372036854775806,1,1,1000,0,0);
138142
FLUSH TABLES;
139143
CHECK TABLE s;
140144
Table Op Msg_type Msg_text
141-
test.s check Warning More than one row in the table
142-
test.s check status OK
145+
test.s check Warning InnoDB: Should have only one record in sequence table test/s. But it has 2 records.
146+
test.s check error Corrupt
143147
DROP SEQUENCE s;

mysql-test/suite/sql_sequence/check.test

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,11 +147,16 @@ let $datadir=`select @@datadir`;
147147
CREATE SEQUENCE s engine=innodb;
148148
copy_file $datadir/test/s.frm $datadir/test/s1.frm;
149149
ALTER TABLE s sequence=0;
150+
--connect (prevent_purge,localhost,root)
151+
START TRANSACTION WITH CONSISTENT SNAPSHOT;
152+
153+
--connection default
150154
delete from s;
151155
FLUSH TABLES;
152156
remove_file $datadir/test/s.frm;
153157
move_file $datadir/test/s1.frm $datadir/test/s.frm;
154158
CHECK TABLE s;
159+
--disconnect prevent_purge
155160
DROP SEQUENCE s;
156161

157162
# Just one row, check ok

0 commit comments

Comments
 (0)