1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-08 11:22:35 +03:00

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
This commit is contained in:
Thirunarayanan Balathandayuthapani
2025-06-06 18:42:30 +05:30
parent 37274ae01f
commit 6a2afb42ba
6 changed files with 395 additions and 3 deletions

View File

@@ -0,0 +1,17 @@
--- check_sequence.result
+++ check_sequence,debug.result
@@ -112,3 +112,14 @@
3
disconnect prevent_purge;
DROP SEQUENCE s1;
+CREATE SEQUENCE s ENGINE=InnoDB;
+ALTER TABLE s SEQUENCE=0;
+FLUSH TABLES;
+SET STATEMENT DEBUG_DBUG="+d,fail_root_page" FOR
+CHECK TABLE s;
+Table Op Msg_type Msg_text
+test.s check Warning InnoDB: Sequence table test/s is corrupted.
+test.s check error Corrupt
+ALTER TABLE s SEQUENCE=1;
+ERROR HY000: InnoDB: Table `test`.`s` is corrupted.
+DROP SEQUENCE s;

View File

@@ -0,0 +1,114 @@
#
# MDEV-36487 Fix ha_innobase::check() for sequences
#
call mtr.add_suppression("InnoDB: Table test/s2 contains 1 indexes .*");
call mtr.add_suppression("Table test/s2 has a primary key in InnoDB .*");
CREATE SEQUENCE s ENGINE=InnoDB;
ALTER TABLE s SEQUENCE=0, ALGORITHM=INPLACE;
ERROR 0A000: ALGORITHM=INPLACE is not supported. Reason: SEQUENCE. Try ALGORITHM=COPY
ALTER TABLE s SEQUENCE=0, ALGORITHM=COPY;
FLUSH TABLES;
CHECK TABLE s;
Table Op Msg_type Msg_text
test.s check Warning InnoDB: Sequence table test/s has ROLLBACK enabled.
test.s check error Corrupt
ALTER TABLE s SEQUENCE=1;
ERROR HY000: InnoDB: Table `test`.`s` is corrupted.
DROP SEQUENCE s;
CREATE SEQUENCE s ENGINE=InnoDB;
CREATE TABLE s2 LIKE s;
ALTER TABLE s2 sequence=0;
INSERT INTO s2 VALUES (3,1,9223372036854775806,1,1,1000,0,0);
ALTER TABLE s2 ADD INDEX idx(start_value);
FLUSH TABLES;
CHECK TABLE s2;
Table Op Msg_type Msg_text
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
test.s2 check Warning InnoDB: Sequence table test/s2 does have more than one indexes.
test.s2 check error Corrupt
ALTER TABLE s2 SEQUENCE=1;
ERROR HY000: InnoDB: Table `test`.`s2` is corrupted.
DROP SEQUENCE s;
DROP SEQUENCE s2;
CREATE SEQUENCE s ENGINE=InnoDB;
CREATE TABLE s2 LIKE s;
ALTER TABLE s2 sequence=0;
INSERT INTO s2 VALUES (3,2,9223372036854775806,2,2,1000,0,0);
ALTER TABLE s2 ADD PRIMARY KEY(start_value);
FLUSH TABLES;
CHECK TABLE s2;
Table Op Msg_type Msg_text
test.s2 check Warning InnoDB: Table test/s2 has a primary key in InnoDB data dictionary, but not in MariaDB!
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
test.s2 check Warning InnoDB: Sequence table test/s2 does not have generated clustered index.
test.s2 check error Corrupt
ALTER TABLE s2 SEQUENCE=1;
ERROR HY000: InnoDB: Table `test`.`s2` is corrupted.
DROP SEQUENCE s;
DROP SEQUENCE s2;
CREATE SEQUENCE s ENGINE=InnoDB;
CREATE TABLE s2 LIKE s;
ALTER TABLE s2 sequence=0;
INSERT INTO s2 VALUES (3,1,9223372036854775806,1,1,1000,0,0);
DELETE FROM s2;
InnoDB 0 transactions not purged
FLUSH TABLES;
CHECK TABLE s2;
Table Op Msg_type Msg_text
test.s2 check Warning InnoDB: Should have only one record in sequence table test/s2. But it has 0 records.
test.s2 check error Corrupt
ALTER TABLE s2 SEQUENCE=1;
ERROR HY000: InnoDB: Table `test`.`s2` is corrupted.
DROP SEQUENCE s;
DROP SEQUENCE s2;
CREATE SEQUENCE s ENGINE=InnoDB;
CREATE TABLE s2 LIKE s;
ALTER TABLE s2 sequence=0;
INSERT INTO s2 select seq, seq, seq, seq, seq, seq, 1, seq from
seq_1_to_200;
FLUSH TABLES;
CHECK TABLE s2;
Table Op Msg_type Msg_text
test.s2 check Warning InnoDB: Non leaf page exists for sequence table test/s2.
test.s2 check error Corrupt
ALTER TABLE s2 SEQUENCE=1;
ERROR HY000: InnoDB: Table `test`.`s2` is corrupted.
DROP SEQUENCE s;
DROP SEQUENCE s2;
CREATE SEQUENCE s ENGINE=InnoDB;
CREATE TABLE s2 LIKE s;
ALTER TABLE s2 sequence=0;
DELETE FROM s2;
InnoDB 0 transactions not purged
connect prevent_purge,localhost,root;
START TRANSACTION WITH CONSISTENT SNAPSHOT;
connection default;
INSERT INTO s2 VALUES (3,1,9223372036854775806,1,1,1000,0,0);
FLUSH TABLES;
CHECK TABLE s2;
Table Op Msg_type Msg_text
test.s2 check Warning InnoDB: Record in sequence table test/s2 is corrupted.
test.s2 check error Corrupt
ALTER TABLE s2 SEQUENCE=1;
ERROR HY000: InnoDB: Table `test`.`s2` is corrupted.
DROP SEQUENCE s;
DROP SEQUENCE s2;
CREATE SEQUENCE s1 ENGINE=InnoDB;
CHECK TABLE s1;
Table Op Msg_type Msg_text
test.s1 check status OK
connection prevent_purge;
START TRANSACTION WITH CONSISTENT SNAPSHOT;
connection default;
INSERT INTO s1 VALUES (3,1,9223372036854775806,1,1,1000,0,0);
SELECT * FROM s1;
next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
3 1 9223372036854775806 1 1 1000 0 0
CHECK TABLE s1;
Table Op Msg_type Msg_text
test.s1 check status OK
select nextval(s1);
nextval(s1)
3
disconnect prevent_purge;
DROP SEQUENCE s1;

View File

@@ -0,0 +1,136 @@
--source include/have_innodb.inc
--source include/have_sequence.inc
--source include/maybe_debug.inc
--echo #
--echo # MDEV-36487 Fix ha_innobase::check() for sequences
--echo #
call mtr.add_suppression("InnoDB: Table test/s2 contains 1 indexes .*");
call mtr.add_suppression("Table test/s2 has a primary key in InnoDB .*");
# Sequence table which has NO_ROLLBACK flag set
let $datadir=`select @@datadir`;
CREATE SEQUENCE s ENGINE=InnoDB;
copy_file $datadir/test/s.frm $datadir/test/s1.frm;
--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
ALTER TABLE s SEQUENCE=0, ALGORITHM=INPLACE;
ALTER TABLE s SEQUENCE=0, ALGORITHM=COPY;
FLUSH TABLES;
remove_file $datadir/test/s.frm;
move_file $datadir/test/s1.frm $datadir/test/s.frm;
CHECK TABLE s;
--error ER_TABLE_CORRUPT
ALTER TABLE s SEQUENCE=1;
DROP SEQUENCE s;
# Checks for more than one index
CREATE SEQUENCE s ENGINE=InnoDB;
copy_file $datadir/test/s.frm $datadir/test/orig.frm;
CREATE TABLE s2 LIKE s;
ALTER TABLE s2 sequence=0;
INSERT INTO s2 VALUES (3,1,9223372036854775806,1,1,1000,0,0);
ALTER TABLE s2 ADD INDEX idx(start_value);
FLUSH TABLES;
move_file $datadir/test/orig.frm $datadir/test/s2.frm;
CHECK TABLE s2;
--error ER_TABLE_CORRUPT
ALTER TABLE s2 SEQUENCE=1;
DROP SEQUENCE s;
DROP SEQUENCE s2;
# Checks for generated clustered index
CREATE SEQUENCE s ENGINE=InnoDB;
copy_file $datadir/test/s.frm $datadir/test/orig.frm;
CREATE TABLE s2 LIKE s;
ALTER TABLE s2 sequence=0;
INSERT INTO s2 VALUES (3,2,9223372036854775806,2,2,1000,0,0);
ALTER TABLE s2 ADD PRIMARY KEY(start_value);
FLUSH TABLES;
move_file $datadir/test/orig.frm $datadir/test/s2.frm;
CHECK TABLE s2;
--error ER_TABLE_CORRUPT
ALTER TABLE s2 SEQUENCE=1;
DROP SEQUENCE s;
DROP SEQUENCE s2;
# Should contain only one record
CREATE SEQUENCE s ENGINE=InnoDB;
copy_file $datadir/test/s.frm $datadir/test/orig.frm;
CREATE TABLE s2 LIKE s;
ALTER TABLE s2 sequence=0;
INSERT INTO s2 VALUES (3,1,9223372036854775806,1,1,1000,0,0);
DELETE FROM s2;
--source include/wait_all_purged.inc
FLUSH TABLES;
move_file $datadir/test/orig.frm $datadir/test/s2.frm;
CHECK TABLE s2;
--error ER_TABLE_CORRUPT
ALTER TABLE s2 SEQUENCE=1;
DROP SEQUENCE s;
DROP SEQUENCE s2;
# More than one page
CREATE SEQUENCE s ENGINE=InnoDB;
copy_file $datadir/test/s.frm $datadir/test/orig.frm;
CREATE TABLE s2 LIKE s;
ALTER TABLE s2 sequence=0;
INSERT INTO s2 select seq, seq, seq, seq, seq, seq, 1, seq from
seq_1_to_200;
FLUSH TABLES;
move_file $datadir/test/orig.frm $datadir/test/s2.frm;
CHECK TABLE s2;
--error ER_TABLE_CORRUPT
ALTER TABLE s2 SEQUENCE=1;
DROP SEQUENCE s;
DROP SEQUENCE s2;
# Checks for DB_TRX_ID & DB_ROLL_PTR in the record
CREATE SEQUENCE s ENGINE=InnoDB;
copy_file $datadir/test/s.frm $datadir/test/orig.frm;
CREATE TABLE s2 LIKE s;
ALTER TABLE s2 sequence=0;
DELETE FROM s2;
--source include/wait_all_purged.inc
--connect (prevent_purge,localhost,root)
START TRANSACTION WITH CONSISTENT SNAPSHOT;
--connection default
INSERT INTO s2 VALUES (3,1,9223372036854775806,1,1,1000,0,0);
FLUSH TABLES;
move_file $datadir/test/orig.frm $datadir/test/s2.frm;
CHECK TABLE s2;
--error ER_TABLE_CORRUPT
ALTER TABLE s2 SEQUENCE=1;
DROP SEQUENCE s;
DROP SEQUENCE s2;
# Insert a row into a sequence table updates that row
CREATE SEQUENCE s1 ENGINE=InnoDB;
CHECK TABLE s1;
--connection prevent_purge
START TRANSACTION WITH CONSISTENT SNAPSHOT;
--connection default
INSERT INTO s1 VALUES (3,1,9223372036854775806,1,1,1000,0,0);
SELECT * FROM s1;
CHECK TABLE s1;
--disable_ps2_protocol
select nextval(s1);
--enable_ps2_protocol
--disconnect prevent_purge
DROP SEQUENCE s1;
if ($have_debug)
{
# Root page is corrupted
CREATE SEQUENCE s ENGINE=InnoDB;
copy_file $datadir/test/s.frm $datadir/test/s1.frm;
ALTER TABLE s SEQUENCE=0;
FLUSH TABLES;
remove_file $datadir/test/s.frm;
move_file $datadir/test/s1.frm $datadir/test/s.frm;
SET STATEMENT DEBUG_DBUG="+d,fail_root_page" FOR
CHECK TABLE s;
--error ER_TABLE_CORRUPT
ALTER TABLE s SEQUENCE=1;
DROP SEQUENCE s;
}