mariadb/mysql-test/suite/innodb/t/innochecksum_flags_and_skip.test
Thirunarayanan Balathandayuthapani e4f8ab2624 MDEV-37138: Innochecksum fails to handle doublewrite buffer and
multiple file tablespace

Problem:
=======
- innochecksum was incorrectly interpreting doublewrite buffer
pages as index pages, causing confusion about stale tables
in the system tablespace.

- innochecksum fails to parse the multi-file system tablespace

Solution:
========
1. Doublewrite buffer pages and rewrite checksum of
doublewrite buffer pages are skipped when skip_freed_pages
is enabled.

2. Introduced the option --tablespace-flags which can be used
to initialize page size. This option can handle the ibdata2,
ibdata3 etc without parsing ibdata1.
2025-09-26 15:39:42 +05:30

116 lines
3.8 KiB
Text

--source include/have_innodb.inc
--source include/not_embedded.inc
--source include/have_debug.inc
let MYSQLD_DATADIR= `SELECT @@datadir`;
CREATE TABLE t1(a INT PRIMARY KEY) ENGINE=InnoDB STATS_PERSISTENT=0;
SET GLOBAL innodb_log_checkpoint_now=ON;
FLUSH TABLE t1 FOR EXPORT;
UNLOCK TABLES;
INSERT INTO t1 SET a=1;
FLUSH TABLE t1 FOR EXPORT;
UNLOCK TABLES;
let INDEX_ID= `select INDEX_ID FROM INFORMATION_SCHEMA.INNODB_SYS_INDEXES WHERE TABLE_ID = (SELECT TABLE_ID FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME="test/t1")`;
let FLAG= `SELECT flag FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE NAME="innodb_system"`;
let $shutdown_timeout=0;
--source include/shutdown_mysqld.inc
let $resultlog=$MYSQLTEST_VARDIR/tmp/result.log;
let $resultlog_1=$MYSQLTEST_VARDIR/tmp/result_1.log;
exec $INNOCHECKSUM -S -r $MYSQLD_DATADIR/ibdata1 > $resultlog;
--echo # Skip InnoDB Doublewrite Buffer
exec $INNOCHECKSUM -S $MYSQLD_DATADIR/ibdata1 > $resultlog_1;
perl;
use strict;
use warnings;
use File::Spec::Functions qw(catfile);
sub check_index_in_file {
my ($filename, $search_id, $file_desc) = @_;
my $found = 0;
open(my $fh, '<', $filename) or die "Could not open file '$filename': $!\n";
my $line_count = 0;
while (my $line = <$fh>) {
$line_count++;
chomp $line;
# Skip empty lines and header lines
next if $line =~ /^\s*$/;
next if $line =~ /index_id.*#pages/; # Skip header line
# Split the line by whitespace
my @fields = grep { $_ ne '' } split(/\s+/, $line);
next unless @fields; # Skip if no fields
# The first field is the index_id
my $current_id = $fields[0];
# Check if this is the ID we're looking for
if (defined $current_id && $current_id eq $search_id) {
$found = 1;
last;
}
}
if ($found) {
print "Index ID $search_id FOUND \n";
} else {
print "Index ID $search_id NOT FOUND \n";
}
close $fh;
}
my $search_id = $ENV{'INDEX_ID'};
# Define file paths
my $resultlog = catfile($ENV{'MYSQLTEST_VARDIR'}, 'tmp', 'result.log');
my $resultlog_1 = catfile($ENV{'MYSQLTEST_VARDIR'}, 'tmp', 'result_1.log');
# Check both files
print "Should not exist when summary excludes dblwr pages\n";
check_index_in_file($resultlog, $search_id, 'result.log');
print "Should exist when summary includes dblwr pages\n";
check_index_in_file($resultlog_1, $search_id, 'result_1.log');
EOF
remove_file $resultlog;
remove_file $resultlog_1;
# We expect deterministic checksum error when we pass
# incorrect wrong flags to innochecksum. Below restart is needed
# to make sure that we flush all the pages.
--source include/start_mysqld.inc
CREATE TABLE ibd_1(f1 INT PRIMARY KEY)ENGINE=InnoDB;
INSERT INTO ibd_1 VALUES(1), (2), (3), (4);
let $shutdown_timeout=;
--source include/shutdown_mysqld.inc
--echo # Pass wrong tablespace flag for ibdata2
--error 1
exec $INNOCHECKSUM -S -l $resultlog --tablespace_flags=39 $MYSQLD_DATADIR/ibdata2;
let SEARCH_FILE=$resultlog;
let SEARCH_PATTERN=checksum mismatch fails;
--source include/search_pattern_in_file.inc
remove_file $resultlog;
--echo # Pass wrong tablespace flag for ibdata1
--error 1
exec $INNOCHECKSUM -S -l $resultlog --tablespace_flags=39 $MYSQLD_DATADIR/ibdata1;
let SEARCH_PATTERN=Fail: Mismatch between provided tablespace flags;
--source include/search_pattern_in_file.inc
remove_file $resultlog;
--echo # Pass invalid tablespace flag for ibdata1, skip invalid flag
--echo # read page_size from page 0
exec $INNOCHECKSUM -S --tablespace_flags=89 $MYSQLD_DATADIR/ibdata1 > $resultlog;
remove_file $resultlog;
--echo # innochecksum should be succesfull
exec $INNOCHECKSUM -S --tablespace_flags=$FLAG $MYSQLD_DATADIR/ibdata2 > $resultlog;
let SEARCH_PATTERN=Fail;
--source include/search_pattern_in_file.inc
--source include/start_mysqld.inc
DROP TABLE t1, ibd_1;
remove_file $resultlog;